WPF : Как сделать привязку SystemColors в DataGrid?

В приложении используется DataGrid в котором отображаются строки. Задача сделать так, что бы выделенная строка SelectedItem отображалась цветом, вне зависимости доступен ли DataGrid в данный момент или нет. При этом в приложении есть ночная тема, в которой цвета должны быть другими. Я создал класс ColorThemeManager, в котором хранятся цвета для обеих тем. В основном коде привязка прекрасно работает

<Window Background="{Binding ColorThemeManager.MainBackGroundColor}">

Но с DataGrid привязка не срабатывает :

                    <DataGrid ItemsSource="{Binding CurrentTestDevice.TestsSpecifications}">
                          <DataGrid.Resources>
                              <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="{Binding ColorThemeManager.SelectedRowColor"/>
                              <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="{Binding DataContext.ColorThemeManager.SelectedRowColor, RelativeSource={RelativeSource AncestorType=Window}}"/>
                              <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="{Binding DataContext.ColorThemeManager.SelectedRowForegroundColor, RelativeSource={RelativeSource AncestorType=Window}}"/>
                              <SolidColorBrush x:Key="{x:Static SystemColors.GrayTextBrushKey}" Color="Red"/>
                          </DataGrid.Resources>
                                  ...
                    </DataGrid>

Пробовал по разному. Срабатывает только вариант указать цвет явно, как в последнем варианте. Как правильно выполнить Binding в этом случае? Или есть какой-то ещё способ задать цвет выделенной строки и её текста?


Ответы (1 шт):

Автор решения: Cost

Вообще использовать слой ViewModel для хранения конкретных цветов для ночной и дневной темы не самая лучшая идея. Цвета - это всё же ответственность слоя View. Мы можем задать разные стили для дневной и ночной тем:

<Style x:Key="darkTheme">
    <Style.Resources>
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
                         Color="Red"/>
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}"
                         Color="Yellow"/>
    </Style.Resources>
</Style>
<Style x:Key="mainTheme">
    <Style.Resources>
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" 
                         Color="Blue"/>
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}"
                         Color="Green"/>
    </Style.Resources>
</Style>

ViewModel будет содержать лишь флаг IsDark, который даст понять, какой из стилей выбрать, а выбор стиля сделаем по триггеру:

<Style TargetType="DataGrid">
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsDark}" Value="True">
            <Setter Property="ItemContainerStyle" 
                    Value="{StaticResource darkTheme}"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding IsDark}" Value="False">
            <Setter Property="ItemContainerStyle" 
                    Value="{StaticResource mainTheme}"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

Ну а эти три стиля поместим или в отдельный словарь стилей и подключим к окну, или в ресурсы окна:

<Window.Resources>
    <Style x:Key="darkTheme".../>
    <Style x:Key="mainTheme".../>
    <Style TargetType="DataGrid".../>
</Window.Resources>
→ Ссылка