我确实将一个Object绑定到DataGridTextColumn
,并希望从相应的CellStyle中引用其中一个属性。我假设此列的每个单元格都包含MyObject
的实例。但是我无法在DataGridCell
中找到对象的引用(我使用了一个简单的转换器来设置断点并搜索DataGridCell
- 对象已经有一段时间了。)
我正在寻找属性MyObject.IsEnabled,并希望在下面的代码中用 ??? 注明的Path-Property中引用它。有什么建议吗?
<DataGridTextColumn Binding="{Binding MyObject}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Path="???" Binding="{Binding RelativeSource={RelativeSource Self}, PresentationTraceSources.TraceLevel=High,Converter={StaticResource debugger}}" Value="False">
<!-- some setters -->
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
修改
由于我希望稍后将此样式应用于我的DataGrid的所有单元格,因此必须通过RelativeSource
找到绑定到单元格的对象,而不是向MyObject
添加硬编码绑定。
解
由于antiocol的输入,我能够为我的案例找到一个可能适用于类似问题的解决方案。
由于问题是我们无法访问来自CellModel
的Cell或CellStyle
的值,因此我们使用DataGridCell
上的附加属性来存储整个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
而不是单个列。
<Window.Resources>
<converter:CellToEnabledConverter x:Key="CellToEnabledConverter" />
<Style x:Key="DataGridCellStyle" TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Value="False">
<DataTrigger.Binding>
<!--This Converter works only on DataGridTextColumns with this minimal example!-->
<Binding Converter="{StaticResource CellToEnabledConverter}">
<Binding RelativeSource="{RelativeSource Self}" />
</Binding>
</DataTrigger.Binding>
<!--Setters-->
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<DataGrid CellStyle="{StaticResource DataGridCellStyle}">
<DataGridTextColumn Binding="{Binding MyObject.Value}"/>
</DataGrid>
由于我在网上发现了一些评论,指出“使用当前DataGrid
无法根据其值设置单元格样式”,我希望这种解决方法可以帮助某人。
答案 0 :(得分:1)
我一直在为你的问题尝试另一种解决方案。
<Style x:Key="DataGridCellStyle" TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=., RelativeSource={RelativeSource Self}, Converter={StaticResource DataGridCellToBooleanConverter}, ConverterParameter=IsEnabled}" Value="True">
<Setter Property="Background" Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
</Style>
<DataGrid CellStyle="{StaticResource DataGridCellStyle}">
<DataGrid.Columns>
<DataGridTextColumn Header="MyObject1" Binding="{Binding MyObject1}" />
<DataGridTextColumn Header="MyObject2" Binding="{Binding MyObject2}" />
</DataGrid.Columns>
</DataGrid>
另一方面,我认为ItemsSource
的{{1}}是DataGrid
个对象的集合(当然还有类似的东西)
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
中绑定的属性的名称。
P.S。您可以使用反射而不是hacky DataTrigger
元素,但这适用于我。
希望这有帮助
答案 1 :(得分:0)
我唯一能想到的是将每个DataGridTextColumn
切换为DataGridTemplateColumn
,并在每个CellTemplate
内添加一些ContentControl,其DataContext绑定到该列中的属性。< / p>
通过这种方式,您可以为该ContentControl创建可重用的样式,因为DataGridCell
对您没有任何帮助:P
<Style x:Key="MyObjectStyle" TargetType="{x:Type ContentControl}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<!-- your TextBlock and stuff -->
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsEnabled, PresentationTraceSources.TraceLevel=High, Converter={StaticResource debugger}}" Value="False">
<!-- some setters -->
</DataTrigger>
</Style.Triggers>
</Style>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ContentControl Content="{Binding MyObject}"
Style="{StaticResource MyObjectStyle}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
答案 2 :(得分:-1)
你必须首先修复DataTrigger的sintax,如下所示:
<DataGridTextColumn Binding="{Binding MyObject}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding MyObject.IsEnabled, PresentationTraceSources.TraceLevel=High, Converter={StaticResource debugger}}" Value="False">
<!-- some setters -->
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
注意DataTrigger的Binding属性。由于每个Path
中的IsEnabled
将是{{1}的实例,因此您必须在DataContext
中编写DataGridCell
该属性对象。您不需要使用MyObject
,因为您的RelativeSource
指向Binding
,如前所述。
如果要将此样式创建为资源,可以执行以下操作:
MyObject