I did bind an Object to a DataGridTextColumn
and would like to reference one of its properties from within the corresponding CellStyle. I assumed that each cell of this column would contain an instance of MyObject
. However I can't find a reference to the Object from within the DataGridCell
(I used a trivial converter to set a break point and searched the DataGridCell
-object for quite a while).
I am looking for the Property MyObject.IsEnabled and would like to reference that in the Path-Property noted with ??? in the code below. Any suggestions?
<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>
EDIT:
Since i want to apply this style to all Cells of my DataGrid later on it is essential to find the object which is bound to the cell via RelativeSource
instead of adding a hardcoded binding to MyObject
.
SOLUTION
Thanks to the input of antiocol i was able to find a solution for my case which possibly can be adapted to similar problems.
Since the problem is that we don't have access to the values of the Cell or a CellModel
from within the CellStyle
, we use an attached Property on the DataGridCell
to store the whole CellModel
in there. From there we can bind any accessible Property of the DataGridCell
to any Property of our CellModel
.
code for attached property:
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));
We need to set this property on every cell in our DataGrid. I didn't find a good solution to do this in XAML, so for now I set it in the converter before I retrieve the information. (suggestions for improvement appreciated)
Converter:
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;
}
Now we can define a global Style
in XAML and apply it to the whole DataGrid
instead of a single column.
<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>
Since i found several comments on the net stating that "styling a cell depending on its value just is not possible with the current DataGrid
", i hope this workaround helps someone out.
ItemsSource
forDataGrid
? – DennisDataContext
of the cell is entireRowModel
. I'm afraid, you can't getCellModel
in the style. – Dennis<DataGridTextColumn Binding="{Binding MyObject}">
. Where is this object actually bound to? I went through most of the visual tree (including DataGrid, DataGridView, DataGridCellsPresenter, DataGridCell) and could not find a Property to whichMyObject
is bound. The GUI still shows the properToString()
value of my object, so the reference has to be SOMEwhere?! – H WRowModel
. When DG have to render the row, it looks into binding expression for particular column, and resolves its value to render in cell. Resolving doesn't change data context of the cell. – Dennis