Почему я не могу использовать DynamicResource с DataGridColumn.CellStyle

Итак, например, у меня есть приложение MVVM WPF с простой моделью:

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

и простая модель представления, которая создает 3 строки:

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"}
            };
    }
}

И у меня есть DataGrid с определенными вручную столбцами, и для каждого столбца я устанавливаю CellStyle. Оба стиля определены в блоке Window.Resources. Но для первого столбца я использую StaticResource, а для второго DynamicResource

Просмотр 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.

см. второй столбец


person Envilogger    schedule 04.07.2013    source источник
comment
Это похоже на ожидаемое поведение для меня? Можете ли вы уточнить, в чем, по вашему мнению, проблема?   -  person MoonKnight    schedule 04.07.2013
comment
Проблема в том, что CellStyle это DependencyProperty, но когда я пытаюсь использовать в нем привязку, это не работает. Очевидно, они сделали это DependencyProperty не просто так.   -  person Envilogger    schedule 04.07.2013
comment
Что произойдет, если вы переместите стиль BaseCellClass в ресурсы вашего приложения (или в другое место, которое загружается до инициализации Window)?   -  person Brian S    schedule 04.07.2013
comment
Использование DynamicResources в DataGrid — не лучшая идея, StaticResource извлекается только один раз ссылочным элементом и используется в течение всего срока службы ресурса. DynamicResource приобретаются каждый раз, когда используется объект, на который делается ссылка. Снижение производительности в Datagrid со многими элементами будет довольно большим, также, если вы объявляете ресурс в том же файле, нет необходимости использовать DynamicResource.   -  person sa_ddam213    schedule 05.07.2013
comment
Полностью согласен с @sa_ddam213. В вашем случае вам нужно использовать Converters, DynamicResource бесполезно.   -  person Anatoliy Nikolaev    schedule 05.07.2013
comment
Да, StaticResource будет работать нормально, но в моем случае мне нужно использовать DynamicResource. Этот пример кода я сделал только для того, чтобы проиллюстрировать проблему. В нашем реальном приложении цель состоит в том, чтобы использовать DynamicResource, чтобы иметь возможность изменять стили на лету. Во всяком случае, я думаю, что это невозможно с базовой реализацией DataGridColumn, и я ищу другие способы   -  person Envilogger    schedule 05.07.2013


Ответы (2)


Вы можете создать ресурсы для свойств в DataGridCell Style, а затем указать их как DynamicResource в определении Style:

Исходя из вашего примера, это будет выглядеть так:

<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>

Ресурсы, конечно, будут расположены в отдельных файлах ресурсов.

person Richard E    schedule 05.07.2013
comment
Спасибо. Ваша душа работает нормально. Но в вопросе я забыл сказать, что мне нужен способ получения стилей, как в этом вопросе: stackoverflow.com/questions/9490264/ - person Envilogger; 05.07.2013
comment
В любом случае, я отмечу ваш ответ как правильный и опубликую свое собственное решение, в котором я мало использую для этого - person Envilogger; 05.07.2013

Я нашел решение с помощью небольшого сервиса. В двух словах я пишу в xaml этот код:

<wpfApplication12:DataGridColumnDynamicStyleService TargetGrid="{Binding ElementName=Grid}">
        <wpfApplication12:DataGridColumnDynamicStyleService.ColumnStyles>
            <wpfApplication12:DataGridColumnStyleBinding ColumnTag="C1" DynamicStyle="{DynamicResource BaseCellClass}" />
        </wpfApplication12:DataGridColumnDynamicStyleService.ColumnStyles>
    </wpfApplication12:DataGridColumnDynamicStyleService>
    <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding ElementName=WholeWindow, Path=ViewModel.Objects}" x:Name="Grid">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding F1}" Header="F1" wpfApplication12:DataGridColumnDynamicStyle.ColumnTag="C1" />
            <DataGridTextColumn Binding="{Binding F2}" Header="F2" wpfApplication12:DataGridColumnDynamicStyle.ColumnTag="C2" />
        </DataGrid.Columns>
    </DataGrid>

Здесь, как видите, я использую присоединенное свойство ColumnTag для идентификации столбцов. И я создаю элемент управления службой, который определяет стили для столбцов и устанавливает целевую сетку данных как TargetGrid. Если вы хотите увидеть весь код, вот ссылка на решение на гугл диск

person Envilogger    schedule 05.07.2013