当鼠标移动时突出显示WPF DataGrid上的列

sbe*_*rli 0 .net wpf datagrid effects .net-4.0

我希望在鼠标移动时突出显示WPF数据网格上的列.我面临的一些问题是:

  • 获取列的坐标以测试鼠标何时位于它们之上
  • 更改列的背景颜色

任何帮助都感激不尽.

ASa*_*nch 6

如何更新DataGridCell的样式并在其中定义"IsMouseOver"触发器?像这样的东西:

<DataGrid x:Name="dg">
    <DataGrid.Resources>
        <Style x:Key="{x:Type DataGridCell}" TargetType="{x:Type DataGridCell}">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="true">
                    <Setter Property="Background" Value="LightGray"/>
                </Trigger>
                <Trigger Property="IsSelected" Value="true">
                    <Setter Property="Background" Value="Blue" />
                    <Setter Property="Foreground" Value="White" />
                    <Setter Property="BorderBrush" Value="Black" />
                </Trigger>
                <Trigger Property="IsKeyboardFocusWithin" Value="true">
                    <Setter Property="BorderBrush" Value="Gray" />
                </Trigger>
            </Style.Triggers>
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="BorderBrush" Value="Transparent" />
            <Setter Property="BorderThickness" Value="1" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridCell}">
                        <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" 
                                BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="true">
                            <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGrid.Resources>
</DataGrid>
Run Code Online (Sandbox Code Playgroud)

编辑:

下面是一个解决方案:1)突出显示当前悬停的单元格,2)突出显示整行,3)突出显示整个列.我只是快速编写了这个并且没有彻底测试它,所以你可能会遇到一些问题.但无论如何,这应该让你知道如何完成它们.

我的用于高亮显示整个列方案涉及使用,正在分配给DataGridCell当鼠标在它两个连接的性能.只需检查一下,看看它是否适合您.

XAML:

<Window x:Class="StackOverflow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:StackOverflow"
        Title="MainWindow" Height="350" Width="525">
    <DataGrid x:Name="dg" AutoGenerateColumns="True">
        <DataGrid.Resources>
            <Style x:Key="{x:Type DataGridCell}" TargetType="{x:Type DataGridCell}">
                <Setter Property="Background" Value="Transparent" />
                <Setter Property="BorderBrush" Value="Transparent" />
                <Setter Property="BorderThickness" Value="1" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type DataGridCell}">
                            <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" 
                                BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="true">
                                <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <Trigger Property="local:DataGridBehavior.IsCellHighlighted" Value="True">
                        <Setter Property="Background" Value="LightGray"/>
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="local:DataGridBehavior.HighlightColumn" Value="True"/>
                        <Setter Property="Background" Value="Green"/>
                    </Trigger>
                    <Trigger Property="IsSelected" Value="true">
                        <Setter Property="Background" Value="Blue" />
                        <Setter Property="Foreground" Value="White" />
                        <Setter Property="BorderBrush" Value="Black" />
                    </Trigger>
                    <Trigger Property="IsKeyboardFocusWithin" Value="true">
                        <Setter Property="BorderBrush" Value="Gray" />
                    </Trigger>
                </Style.Triggers>
            </Style>
            <Style TargetType="{x:Type DataGridRow}">
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="LightGray"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </DataGrid.Resources>
    </DataGrid>
</Window>
Run Code Online (Sandbox Code Playgroud)

DataGridBehavior类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Interactivity;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Controls.Primitives;

namespace StackOverflow
{
    public class DataGridBehavior : DependencyObject
    {

        public static bool GetHighlightColumn(DependencyObject obj)
        {
            return (bool)obj.GetValue(HighlightColumnProperty);
        }

        public static void SetHighlightColumn(DependencyObject obj, bool value)
        {
            obj.SetValue(HighlightColumnProperty, value);
        }

        // Using a DependencyProperty as the backing store for HighlightColumn.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HighlightColumnProperty =
            DependencyProperty.RegisterAttached("HighlightColumn", typeof(bool), 
            typeof(DataGridBehavior), new FrameworkPropertyMetadata(false, OnHighlightColumnPropertyChanged));



        public static bool GetIsCellHighlighted(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsCellHighlightedProperty);
        }

        public static void SetIsCellHighlighted(DependencyObject obj, bool value)
        {
            obj.SetValue(IsCellHighlightedProperty, value);
        }

        // Using a DependencyProperty as the backing store for IsCellHighlighted.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsCellHighlightedProperty =
            DependencyProperty.RegisterAttached("IsCellHighlighted", typeof(bool), typeof(DataGridBehavior), 
            new UIPropertyMetadata(false));



        private static void OnHighlightColumnPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            Console.WriteLine(e.NewValue);
            DataGridCell cell = sender as DataGridCell;

            if (cell != null) 
            {
                DataGrid dg = GetDataGridFromCell(cell);
                DataGridColumn column = cell.Column;

                for (int i = 0; i < dg.Items.Count; i++) 
                {
                    DataGridRow row = dg.ItemContainerGenerator.ContainerFromIndex(i) as DataGridRow;
                    DataGridCell currentCell = GetCell(row, column);
                    if (currentCell != null)
                    {
                        currentCell.SetValue(DataGridBehavior.IsCellHighlightedProperty, e.NewValue);
                    }
                }

            }
        }

        private static DataGrid GetDataGridFromCell(DataGridCell cell)
        { 
            DataGrid retVal = null;
            FrameworkElement fe = cell;
            while ((retVal == null) && (fe != null))
            {
                if (fe is DataGrid)
                    retVal = fe as DataGrid;
                else
                    fe = VisualTreeHelper.GetParent(fe) as FrameworkElement;
            }
            return retVal;
        }

        private static DataGridCell GetCell(DataGridRow row, DataGridColumn column) 
        {
            DataGridCell retVal = null;
            DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(row);
            if (presenter != null)
            {
                for (int i = 0; i < presenter.Items.Count; i++)
                {
                    DataGridCell cell = presenter.ItemContainerGenerator.ContainerFromIndex(i) as DataGridCell;
                    if ((cell != null) && (cell.Column == column))
                    {
                        retVal = cell;
                        break;
                    }
                }
            }

            return retVal;
        }

        private static T GetVisualChild<T>(Visual parent) where T : Visual
        {
            T child = default(T);
            int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < numVisuals; i++)
            {
                Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
                child = v as T;
                if (child == null)
                {
                    child = GetVisualChild<T>(v);
                }
                if (child != null)
                {
                    break;
                }
            }
            return child;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,我认为当网格上有很多项目时,这个解决方案会出现问题.不幸的是,由于DataGrid的设计方式,突出显示整个列并不像突出显示单元格或行那样微不足道.所以,对不起它对你来说效果不好. (2认同)