How to use styletrigger without getting suicidal

93 Views Asked by At

sorry, I don't get it... I'm using a explicit styletrigger in a WPF datagrid. What I want is a simple row with blue text color if my variable DisplayCat = 0, and with red text color if DisplayCat = 1.

Furthermore the row should be marked with red borders if selected. In unselected, unfocused rows everything works fine. However, when selected, the HighlightBrushKey, HighlightTextBrushKey, InactiveSelectionHighlightBrushKey and InactiveSelectionHighlightTextBrushKey are overriding my MultiDataTrigger settings. Any idea how to prevent that? Looking forward to your ideas...

App.xaml:

Application x:Class="Test.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:Test"
             StartupUri="MainWindow.xaml">
    <Application.Resources>

        <Style x:Key="DataGridFancy" TargetType="DataGrid">
            <Setter Property="RowHeaderWidth" Value="0"/>
            <Setter Property="SelectionMode" Value="Single"/>
            <Setter Property="IsReadOnly" Value="True"/>
            <Setter Property="AutoGenerateColumns" Value="False"/>
            <Setter Property="HorizontalScrollBarVisibility" Value="Hidden"/>
            <Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
            <Setter Property="Background" Value="{x:Null}"></Setter>
            <Setter Property="GridLinesVisibility" Value="All"/>
            <Setter Property="Margin" Value="0,5,0,5"></Setter>
            <Setter Property="BorderThickness" Value="1,1,1,1"></Setter>
            <Setter Property="BorderBrush" Value="Transparent"></Setter>            
        </Style>

        <Style x:Key="DataGridGColumnheaderFancy" TargetType="DataGridColumnHeader">
            <Setter Property="FontSize" Value="12"></Setter>
            <Setter Property="Background" Value="{x:Null}"></Setter>
            <Setter Property="Foreground" Value="Black"></Setter>
            <Setter Property="SeparatorVisibility" Value="Collapsed"></Setter>
            <Setter Property="HorizontalContentAlignment" Value="Center"></Setter>
        </Style>

        <Style x:Key="DataGridRowFancy" TargetType="DataGridRow">
            <Setter Property="Margin" Value="5"></Setter>
            <Setter Property="FontSize" Value="12"></Setter>
            <Setter Property="Foreground" Value="LightGray"></Setter>
            <Setter Property="Background" Value="Transparent"></Setter>
            <Setter Property="BorderBrush" Value="Transparent" />
            <Setter Property="BorderThickness" Value="1" />
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}" Value="False"/>
                        <Condition Binding="{Binding DisplayCat}" Value="0"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="BorderBrush" Value="Transparent"/>
                    <Setter Property="Foreground" Value="RoyalBlue"/>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}" Value="False"/>
                        <Condition Binding="{Binding DisplayCat}" Value="1"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="BorderBrush" Value="Transparent"/>
                    <Setter Property="Foreground" Value="Crimson"/>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}" Value="False"/>
                        <Condition Binding="{Binding DisplayCat}" Value="2"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="BorderBrush" Value="Transparent"/>
                    <Setter Property="Foreground" Value="DarkOrange"/>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}" Value="False"/>
                        <Condition Binding="{Binding DisplayCat}" Value="3"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="BorderBrush" Value="Transparent"/>
                    <Setter Property="Foreground" Value="Gold"/>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}" Value="False"/>
                        <Condition Binding="{Binding DisplayCat}" Value="4"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="BorderBrush" Value="Transparent"/>
                    <Setter Property="Foreground" Value="Chartreuse"/>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}" Value="False"/>
                        <Condition Binding="{Binding DisplayCat}" Value="5"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="BorderBrush" Value="Transparent"/>
                    <Setter Property="Foreground" Value="Violet"/>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}" Value="True"/>
                        <Condition Binding="{Binding DisplayCat}" Value="0"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="BorderBrush" Value="Crimson"/>
                    <Setter Property="Foreground" Value="RoyalBlue"/>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}" Value="True"/>
                        <Condition Binding="{Binding DisplayCat}" Value="1"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="BorderBrush" Value="Crimson"/>
                    <Setter Property="Foreground" Value="Crimson"/>
                    <Setter Property="Background" Value="DimGray"/>

                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}" Value="True"/>
                        <Condition Binding="{Binding DisplayCat}" Value="2"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="BorderBrush" Value="Crimson"/>
                    <Setter Property="Foreground" Value="DarkOrange"/>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}" Value="True"/>
                        <Condition Binding="{Binding DisplayCat}" Value="3"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="BorderBrush" Value="Crimson"/>
                    <Setter Property="Foreground" Value="Gold"/>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}" Value="True"/>
                        <Condition Binding="{Binding DisplayCat}" Value="4"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="BorderBrush" Value="Crimson"/>
                    <Setter Property="Foreground" Value="Chartreuse"/>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}" Value="True"/>
                        <Condition Binding="{Binding DisplayCat}" Value="5"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="BorderBrush" Value="Crimson"/>
                    <Setter Property="Foreground" Value="Violet"/>
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>

        <Style x:Key="DataGridCellFancy" TargetType="DataGridCell">
            <Setter Property="BorderBrush" Value="Transparent" />
            <Setter Property="BorderThickness" Value="0" />
            <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
        </Style>
    </Application.Resources>
</Application>

MainWindow.xaml:

Window x:Class="Test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" Background="#FF3C3C3C">
    <Grid>
        <DataGrid x:Name="NameGrid" ColumnHeaderStyle="{StaticResource DataGridGColumnheaderFancy}" Style="{StaticResource DataGridFancy}" RowStyle="{StaticResource DataGridRowFancy}" CellStyle="{StaticResource DataGridCellFancy}" ItemsSource="{Binding}" AutoGenerateColumns="False">

            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="*"/>
                <DataGridTextColumn Header="DisplayCat" Binding="{Binding DisplayCat}"/>
            </DataGrid.Columns>
        </DataGrid>

    </Grid>
</Window>

MainWindow.xaml.cs:

using System.Collections.Generic;
using System.Windows;

namespace LotManager_Mobile
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        List<Person> mylist = new List<Person>();

        public MainWindow()
        {
            InitializeComponent();

            string[] names = new string[] { "Peter", "Paul", "Monica", "Daisy", "Mike" };

            int i = 0;

            foreach (string mystring in names)
            {
                Person person = new Person();
                person.Name = mystring;
                person.DisplayCat = i += 1;
                mylist.Add(person);
            }

            NameGrid.ItemsSource = mylist;
        }

        public class Person
        {
            public string Name
            { get; set; } = null;

            public int? DisplayCat
            { get; set; } = null;
        }
    }
}
3

There are 3 best solutions below

2
Sach On

Your Style should be under <DataGrid.ItemContainerStyle>. Also you're missing a closing </MultiDataTrigger> tag.

<DataGrid ItemsSource="{Binding People}" Margin="10" AutoGenerateColumns="True">
    <DataGrid.ItemContainerStyle>
        <Style TargetType="DataGridRow">
            <Setter Property="Margin" Value="5"></Setter>
            <Setter Property="FontSize" Value="12"></Setter>
            <Setter Property="Foreground" Value="LightGray"></Setter>
            <Setter Property="Background" Value="Transparent"></Setter>
            <Setter Property="BorderBrush" Value="Transparent" />
            <Setter Property="BorderThickness" Value="1" />
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}" Value="False"/>
                        <Condition Binding="{Binding DisplayCat}" Value="0"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="BorderBrush" Value="Transparent"/>
                    <Setter Property="Foreground" Value="RoyalBlue"/>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}" Value="False"/>
                        <Condition Binding="{Binding DisplayCat}" Value="1"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="BorderBrush" Value="Transparent"/>
                    <Setter Property="Foreground" Value="Crimson"/>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}" Value="True"/>
                        <Condition Binding="{Binding DisplayCat}" Value="0"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="BorderBrush" Value="Crimson"/>
                    <Setter Property="Foreground" Value="RoyalBlue"/>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}" Value="True"/>
                        <Condition Binding="{Binding DisplayCat}" Value="1"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="BorderBrush" Value="Crimson"/>
                    <Setter Property="Foreground" Value="Crimson"/>
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>
    </DataGrid.ItemContainerStyle>
</DataGrid>
0
BionicCode On

You need to override the ControlTemplate for the DataGridCell.

Microsoft Docs: DataGrid ControlTemplate Example

Add the following Style to a ResourceDictionary within the scope of the DataGrid (e.g. Window.Resources):

<!--Style and template for the DataGridCell.-->
<Style TargetType="{x:Type DataGridCell}">
  <Setter Property="Padding"
          Value="5" />
  <Setter Property="FontSize"
          Value="12" />
  <Setter Property="Foreground"
          Value="LightGray" />
  <Setter Property="Background"
          Value="Transparent" />
  <Setter Property="BorderBrush"
          Value="Transparent" />
  <Setter Property="BorderThickness"
          Value="1" />
  <Setter Property="SnapsToDevicePixels"
          Value="true" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type DataGridCell}">
        <Border x:Name="border"
                Padding="{TemplateBinding Padding}"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                Background="{TemplateBinding Background}">

          <ContentPresenter />
        </Border>
        <ControlTemplate.Triggers>
          <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
              <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}"
                         Value="False" />
              <Condition Binding="{Binding DisplayCat}"
                         Value="0" />
            </MultiDataTrigger.Conditions>
            <Setter Property="BorderBrush"
                    Value="Transparent" />
            <Setter Property="Foreground"
                    Value="RoyalBlue" />
          </MultiDataTrigger>
          <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
              <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}"
                         Value="False" />
              <Condition Binding="{Binding DisplayCat}"
                         Value="1" />
            </MultiDataTrigger.Conditions>
            <Setter Property="BorderBrush"
                    Value="Transparent" />
            <Setter Property="Foreground"
                    Value="Crimson" />
          </MultiDataTrigger>
          <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
              <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}"
                         Value="True" />
              <Condition Binding="{Binding DisplayCat}"
                         Value="0" />
            </MultiDataTrigger.Conditions>
            <Setter Property="BorderBrush"
                    Value="Crimson" />
            <Setter Property="Foreground"
                    Value="RoyalBlue" />
          </MultiDataTrigger>
          <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
              <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}"
                         Value="True" />
              <Condition Binding="{Binding DisplayCat}"
                         Value="1" />
            </MultiDataTrigger.Conditions>
            <Setter Property="BorderBrush"
                    Value="Crimson" />
            <Setter Property="Foreground"
                    Value="Crimson" />
          </MultiDataTrigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

If you need to set the border colors of the row instead of the cell, then you have to override the Style for the DataGridRow too.
Modify font colors (Foreground) in the Style for DataGridCell (and remove the setters for the Border)
and modify row borders in the Style for the DataGridRow:

<!--Style and template for the DataGridRow.-->
<Style TargetType="{x:Type DataGridRow}">
  <Setter Property="Background" 
          Value="Transparent" />
  <Setter Property="BorderThickness" 
          Value="1"/>
  <Setter Property="SnapsToDevicePixels"
          Value="true" />
  <Setter Property="Validation.ErrorTemplate"
          Value="{x:Null}" />
  <Setter Property="ValidationErrorTemplate">
    <Setter.Value>
      <ControlTemplate>
        <TextBlock Foreground="Red"
                   Margin="2,0,0,0"
                   Text="!"
                   VerticalAlignment="Center" />
      </ControlTemplate>
    </Setter.Value>
  </Setter>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type DataGridRow}">
        <Border x:Name="DGR_Border"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                Background="{TemplateBinding Background}">

          <SelectiveScrollingGrid>
            <SelectiveScrollingGrid.ColumnDefinitions>
              <ColumnDefinition Width="Auto" />
              <ColumnDefinition Width="*" />
            </SelectiveScrollingGrid.ColumnDefinitions>
            <SelectiveScrollingGrid.RowDefinitions>
              <RowDefinition Height="*" />
              <RowDefinition Height="Auto" />
            </SelectiveScrollingGrid.RowDefinitions>
            <DataGridCellsPresenter Grid.Column="1"
                                    ItemsPanel="{TemplateBinding ItemsPanel}"
                                    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
            <DataGridDetailsPresenter Grid.Column="1"
                                      Grid.Row="1"
                                      Visibility="{TemplateBinding DetailsVisibility}"
                                      SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen, 
          ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical},
          Converter={x:Static DataGrid.RowDetailsScrollingConverter}, 
          RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
            <DataGridRowHeader Grid.RowSpan="2"
                               SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
                               Visibility="{Binding HeadersVisibility, 
          ConverterParameter={x:Static DataGridHeadersVisibility.Row}, 
          Converter={x:Static DataGrid.HeadersVisibilityConverter}, 
          RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
          </SelectiveScrollingGrid>
        </Border>
        <ControlTemplate.Triggers>
          <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
              <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}"
                         Value="False" />
              <Condition Binding="{Binding DisplayCat}"
                         Value="0" />
            </MultiDataTrigger.Conditions>
            <Setter Property="BorderBrush"
                    Value="Transparent" />
          </MultiDataTrigger>
          <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
              <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}"
                         Value="False" />
              <Condition Binding="{Binding DisplayCat}"
                         Value="1" />
            </MultiDataTrigger.Conditions>
            <Setter Property="BorderBrush"
                    Value="Transparent" />
          </MultiDataTrigger>
          <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
              <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}"
                         Value="True" />
              <Condition Binding="{Binding DisplayCat}"
                         Value="0" />
            </MultiDataTrigger.Conditions>
            <Setter Property="BorderBrush"
                    Value="Crimson" />
          </MultiDataTrigger>
          <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
              <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}"
                         Value="True" />
              <Condition Binding="{Binding DisplayCat}"
                         Value="1" />
            </MultiDataTrigger.Conditions>
            <Setter Property="BorderBrush"
                    Value="Crimson" />
          </MultiDataTrigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
0
Prashant Manjule On
//in .xaml
    <Window.Resources>
        <_classtemp:ValueToForegroundColorConverter x:Key="valueToForeground" />
    </Window.Resources>

                                <DataGridTemplateColumn IsReadOnly="True" x:Name="stockColumn" Header="{StaticResource _stock}" Width="Auto">
                                    <DataGridTemplateColumn.CellTemplate>
                                        <DataTemplate>
                                            <Label Content="Cat" Foreground="{Binding DisplayCat , Converter={StaticResource valueToForeground}}"/>
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellTemplate>
                                </DataGridTemplateColumn>

//in .cs class _classtemp
public class ValueToForegroundColorConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        SolidColorBrush brush = new SolidColorBrush(Colors.Black);

        Double doubleValue = 0.0;
        Double.TryParse(value.ToString(), out doubleValue);

        if (doubleValue = 0)
            brush = new SolidColorBrush(Colors.Blue);


        if (doubleValue = 1)
            brush = new SolidColorBrush(Colors.Red);

        return brush;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}