WPF DataGrid的结构 – 根据值更改单元格
我确实将Object绑定到DataGridTextColumn
并希望从相应的CellStyle中引用其中一个属性。 我假设此列的每个单元格都包含一个MyObject
实例。 但是我无法在DataGridCell
找到对Object的引用(我使用了一个简单的转换器来设置断点并搜索了DataGridCell
-object很长一段时间)。
我正在寻找属性MyObject.IsEnabled,并希望在路径属性中引用??? 在下面的代码中。 有什么建议?
编辑:
由于我希望稍后将此样式应用于我的DataGrid的所有单元格,因此必须通过RelativeSource
查找绑定到单元格的对象,而不是向MyObject
添加硬编码绑定。
解
由于antiocol的输入,我能够为我的案例找到一个可能适用于类似问题的解决方案。
由于问题是我们无法从CellStyle
访问Cell或CellModel
的CellStyle
,因此我们使用DataGridCell
上的附加Property将整个CellModel
存储在那里。 从那里我们可以将DataGridCell
任何可访问属性绑定到我们的CellModel
任何属性。
附属物的代码:
public static class DataGridUtils { public static CellModel GetCellModel(DependencyObject obj) { return (CellModel)obj.GetValue(CellModelProperty); } public static void SetCellModel(DependencyObject obj, CellModel value) { obj.SetValue(CellModelProperty, value); } public static readonly DependencyProperty CellModelProperty = DependencyProperty.RegisterAttached("CellModel", typeof(CellModel), typeof(DataGridUtils), new UIPropertyMetadata(null));
我们需要在DataGrid中的每个单元格上设置此属性。 我没有在XAML中找到一个很好的解决方案,所以现在我在检索信息之前将它设置在转换器中。 (有待改进的建议)
转换器:
public class CellToEnabledConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { var cell = values[0] as DataGridCell; DataGridTextColumn column = cell.Column as DataGridTextColumn; //you should probably check if column is null after casting. Binding b = column.Binding as Binding; //Any suggestions on how to create a Binding to the parent object properly? //I needed this workaround since I bind `MyObject.Value` to the `DataGridTextColumn`, //but need a reference to `MyObject` here. Binding b1 = new Binding(b.Path.Path.Split('.')[0]){ Source = cell.DataContext }; cell.SetBinding(DataGridUtils.CellModelProperty, b1); CellModel c = DataGridUtils.GetCellModel(cell); return c.IsEnabled; }
现在我们可以在XAML中定义全局Style
并将其应用于整个DataGrid
而不是单个列。
由于我在网上发现了几条评论,称“使用当前的DataGrid
无法根据其值设置单元格”,我希望这种解决方法可以帮助某人。
我一直在为你的问题尝试另一种解决方案。
另一方面,我假设您的DataGrid
的ItemsSource
是Element
对象的集合(当然还是类似的东西)
public class Element { public string Name { get; set; } public MyObject MyObject1 { get; set; } public MyObject MyObject2 { get; set; } } public class MyObject { public string Name { get; set; } public bool IsEnabled { get; set; } public override string ToString() { return Name; } }
最后,转换器:
public class DataGridCellToBooleanConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { string propertyToAppend = parameter as string; var cell = value as DataGridCell; var column = cell.Column as DataGridTextColumn; Binding b = column.Binding as Binding; Binding b1 = new Binding(string.Join(".", b.Path.Path, propertyToAppend)) { Source = cell.DataContext }; CheckBox dummy = new CheckBox(); dummy.SetBinding(CheckBox.IsCheckedProperty, b1); return dummy.IsChecked; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
棘手的部分是使用ConverterParameter
来传递要在DataTrigger
绑定的属性的名称。
PS你可以使用reflection而不是hacky CheckBox dummy
元素,但这对我有用。
希望这可以帮助
我唯一能想到的是将每个DataGridTextColumn
切换到DataGridTemplateColumn
并在每个CellTemplate
内部添加一些ContentControl,其DataContext绑定到该列中的属性。
这样你就可以为ContentControl创建一个可重用的Style,因为DataGridCell
对你没有任何帮助:P
你必须首先修复DataTrigger的sintax,如下所示:
注意DataTrigger的Binding属性。 在您必须编写Path
属性中,在您的情况下IsEnabled
由于每个DataGridCell
中的DataContext
将是MyObject
对象的实例。 您不需要使用RelativeSource
因为您的Binding
指向MyObject
,如前所述。
如果要将此样式创建为资源,可以执行以下操作: