WPF DataGrid点击列头选择全列并具有背景色
2019年10月3日改:
最主要的思路还是通过点击(排序)事件获取当前点击的列的名称或者index,然后赋值一个字段,通过字段来判断。
这个过程可以通过行为来完成,也可以通过附加属性来完成。
选择将数据模型继承于类我觉得大概是最慢的一个方法了。但是比较直观的。
完成这个操作,主要是XAML的代码。
主要思路是通过绑定多路数据,在多路转换器中返回布尔值,在通过数据触发器来设置被选择的全列的背景色。
XAML页面主要代码
首先定义DataGridCell
<Style TargetType="DataGridCell" x:Key="dgc"> <Setter Property="Tag" > <Setter.Value> <MultiBinding Converter="{StaticResource T2}"> <Binding Path="DataContext.SelectColumn" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=DataGrid}"/> <Binding Path="Column.Header" RelativeSource="{RelativeSource Mode=Self}" /> </MultiBinding> </Setter.Value> </Setter> <Style.Triggers> <DataTrigger Binding="{Binding Tag,RelativeSource={RelativeSource Mode=Self}}" Value="True">
<!--此处的颜色也可以单独列一个--> <Setter Property="Background" Value="Red"/> </DataTrigger> </Style.Triggers> </Style>
定义转换器并使用
public class ToConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { var a = values[0].ToString(); var b = values[1].ToString(); return a == b ? true : false; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
xaml代码
<local:ToConverter x:Key="T2" /> <!--如果单独绑定颜色可以这么弄,然后通过静态资源绑定到数据触发器的setter即可--> <SolidColorBrush Color="Red" x:Key="color"/>
定义DataGrid并创建排序事件和使用CellStyle如下
<DataGrid Sorting="Dg_Sorting" ItemsSource="{Binding List}" CellStyle="{StaticResource dgc}" x:Name="dg" />
定义数据模型并赋值给DataGrid如下
public class T1 { public string Name { get; set; } public int ID { get; set; } } public class T2:INotifyPropertyChanged { public ObservableCollection<T1> List { get; set; } private string select; public string SelectColumn { get=>select; set { select = value;onchanged(new PropertyChangedEventArgs("SelectColumn")); } } protected void onchanged(PropertyChangedEventArgs args) => PropertyChanged?.Invoke(this, args); public event PropertyChangedEventHandler PropertyChanged; }
创建并赋值
ObservableCollection<T1> t = new ObservableCollection<T1>(); T2 datalist; public MainWindow() { InitializeComponent(); for (var i = 0; i < 20; i++) t.Add(new T1() { ID = i, Name = "i: " + i.ToString() }); datalist = new T2(); datalist.List = t; datalist.SelectColumn = string.Empty; dg.DataContext = datalist; }
最后编写排序事件中的代码如下
private void Dg_Sorting(object sender, DataGridSortingEventArgs e) { datalist.SelectColumn = e.Column.Header.ToString(); e.Handled = true; }
运行截图
如果是想将选定好的单元格添加到DataGrid的SelectCells中
则是需要添加玖彩技术团队的这篇文章中的扩展类
然后关闭DataGrid的虚拟化
VirtualizingPanel.IsVirtualizing="False"
最后在排序事件中编写代码如下
private void Dg_Sorting(object sender, DataGridSortingEventArgs e) { datalist.SelectColumn = e.Column.Header.ToString(); for (var i = 0; i < datalist.List.Count; i++) dg.SelectedCells.Add(new DataGridCellInfo(dg.GetCell(i, e.Column.DisplayIndex))); e.Handled = true; }
****************
迫不得已 我是非常不建议这么操作的。
我建议使用数据绑定,操作数据来改变UI/数据的方式。
一是通过修改绑定数据这样子就可以避免关闭DataGrid的虚拟化
二是操作相对简单,仅仅操作数据即可