【问题标题】:Highlighting columns on a WPF DataGrid as mouse moves鼠标移动时突出显示 WPF DataGrid 上的列
【发布时间】:2025-12-24 19:00:12
【问题描述】:

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

  • 获取列的坐标以在鼠标悬停时进行测试
  • 更改列的背景颜色

任何帮助将不胜感激。

【问题讨论】:

    标签: .net wpf datagrid .net-4.0 effects


    【解决方案1】:

    如何更新 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>
    

    编辑

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

    我突出显示整个列的解决方案涉及使用两个附加属性,当鼠标悬停在 DataGridCell 上时,这些属性被分配给它。只需检查一下,看看它是否适合您。

    XAML:

    <Window x:Class="*.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:*"
            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>
    

    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 *
    {
        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;
            }
        }
    }
    

    【讨论】:

    • 太好了!但它只适用于单个单元格。我怎样才能使它适用于列中的所有单元格?事实上,我也希望突出显示与突出显示的单元格在同一行中的所有单元格。
    • 感谢您的努力!它可以工作,但是性能很慢,我想我会放弃突出显示单元格的整个努力:(
    • 是的,我认为当网格上有很多项目时,此解决方案会出现问题。不幸的是,由于 DataGrid 的设计方式,突出显示整列并不像突出显示单元格或行那么简单。所以,很抱歉它对你来说不够好。
    最近更新 更多