Search code examples
c#wpfdatagriddynamicresourcedatagridcolumn

Why can't I use DynamicResource with DataGridColumn.CellStyle


So, for example I have some MVVM WPF application with simple model:

public class MyObject
{
    public string F1 { get; set; }
    public string F2 { get; set; }
}

and simple view model that creates 3 rows:

public class MyViewModel
{
    public ObservableCollection<MyObject> Objects { get; set; }

    public MyViewModel()
    {
        Objects = new ObservableCollection<MyObject>
            {
                new MyObject{F1 = "V1",F2 = "B1"},
                new MyObject{F1 = "V2",F2 = "B2"},
                new MyObject{F1 = "V3",F2 = "V3"}
            };
    }
}

And in view I have a DataGrid with manually defined columns and for each column I set CellStyle. Both styles defined in Window.Resources block. But for first column, I use StaticResource and for the second DynamicResource

View XAML:

<Window x:Class="WpfApplication12.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525" x:Name="WholeWindow">
<Window.Resources>
    <Style x:Key="BaseCellClass" TargetType="DataGridCell">
        <Setter Property="Foreground" Value="Blue" />
    </Style>
</Window.Resources>
<Grid>
    <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding ElementName=WholeWindow, Path=ViewModel.Objects}">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding F1}" Header="F1" CellStyle="{StaticResource BaseCellClass}" />
            <DataGridTextColumn Binding="{Binding F2}" Header="F2" CellStyle="{DynamicResource BaseCellClass}" />
        </DataGrid.Columns>
    </DataGrid>
</Grid>

So the problem is: in the second column, the resource doesn't get applied to the column.

see second column


Solution

  • You could create resources for the properties in your DataGridCell Style and then reference them as a DynamicResource within the Style definition:

    Based on your example it would look like this:

    <Window.Resources>
        <SolidColorBrush x:Key="ForegroundBrush" Color="Blue"/>
    
        <Style x:Key="BaseCellClass" TargetType="DataGridCell">
            <Setter Property="Foreground" Value="{DynamicResource ForegroundBrush}" />
        </Style>
    </Window.Resources>
    <Grid>
        <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding ElementName=WholeWindow, Path=ViewModel.Objects}">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding F1}" Header="F1" CellStyle="{StaticResource BaseCellClass}" />
                <DataGridTextColumn Binding="{Binding F2}" Header="F2" CellStyle="{StaticResource BaseCellClass}" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
    

    The resources would of course be located in separate resource files.