Search code examples
wpfxamldatatriggerdatagridrow

How to apply styles to DataGridRow with DataTrigger


I am trying to apply some conditional styles to DataGridRow, this is what I have so far:

  <DataGrid.ItemContainerStyle>
    <Style TargetType="{x:Type DataGridRow}" BasedOn="{StaticResource {x:Type DataGridRow}}">
      <Style.Triggers>
        <DataTrigger Value="True">
          <DataTrigger.Binding>
            <MultiBinding Converter="{StaticResource SBCInvalidHighlightConverter}">
              <Binding Path="." />
              <Binding Path="DataContext.SelectedCaseType" RelativeSource="{RelativeSource AncestorType=DataGrid}" />
              <Binding Path="IsSelected" RelativeSource="{RelativeSource AncestorType=DataGridRow}"/>
            </MultiBinding>
          </DataTrigger.Binding>
          <Setter Property="Foreground" Value="Red"/>
          <Setter Property="ToolTip">
            <Setter.Value>
              <TextBlock Text="This criteria will not be applied"/>
            </Setter.Value>
          </Setter>
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </DataGrid.ItemContainerStyle>

Basically I am trying to run this converter SBCInvalidHighlightConverter to do three things:

  1. Apply a red font when the converter returns true (an invalid record)

  2. Apply a red font also when the row is selected and the convertor returns true, at the moment it changes to a default of white when selected, I want it to stay red.

  3. Show a tooltip when the converter comes back true, at the moment it just pops up a box saying "System.Windows.Controls.TextBlock"

I am getting the first one to work, but not the second and third.

Image showing selection and cursor hover with popup text:

enter image description here

So the question is: how do I get items 2 & 3 to work?

And here is the the converter, not sure if needed or not:

  public class SBCInvalidHighlightConverter : IMultiValueConverter
  {
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
      bool result = false;

      if (values == null || values.Length < 2)
        return result;

      CTS_EF_DAL.RBCRuleValueForDisplay rowData = (CTS_EF_DAL.RBCRuleValueForDisplay)values[0];

      SBC.SubstanceTypeCode criteriaType = (SBC.SubstanceTypeCode)rowData.Rule_Typ_Cd;
      SBC.CaseType caseType = (SBC.CaseType)((int)values[1]);

      if (caseType != SBC.CaseType.All)
      {
        var caseTypeAttribute = criteriaType.GetAttribute<SBC.CaseTypeAttribute>();
        if (caseTypeAttribute != null && caseTypeAttribute.CaseType != SBC.CaseType.All)
        {
          if (caseTypeAttribute.CaseType != caseType)
          {
            return true; //It is invalid
          }
        }
      }

      return result;
    }

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

Solution

  • If you want to change the Foreground, you should specify a CellStyle rather than a RowStyle.

    You may also set the ToolTip property to a string directly. Just make sure that you don't set the ToolTip property elsewhere outside of the Style.

    Try this:

    <DataGrid.CellStyle>
        <Style TargetType="{x:Type DataGridCell}">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridCell}">
                        <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                            <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
                    <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                </Trigger>
                <Trigger Property="IsKeyboardFocusWithin" Value="True">
                    <Setter Property="BorderBrush" Value="{DynamicResource {x:Static DataGrid.FocusBorderBrushKey}}"/>
                </Trigger>
                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="IsSelected" Value="true"/>
                        <Condition Property="Selector.IsSelectionActive" Value="false"/>
                    </MultiTrigger.Conditions>
                    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
                    <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/>
                </MultiTrigger>
                <Trigger Property="IsEnabled" Value="false">
                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                </Trigger>
                <DataTrigger Value="True">
                    <DataTrigger.Binding>
                        <MultiBinding Converter="{StaticResource SBCInvalidHighlightConverter}">
                            <Binding Path="." />
                            <Binding Path="DataContext.SelectedCaseType" RelativeSource="{RelativeSource AncestorType=DataGrid}" />
                            <Binding Path="IsSelected" RelativeSource="{RelativeSource AncestorType=DataGridRow}"/>
                        </MultiBinding>
                    </DataTrigger.Binding>
                    <Setter Property="Foreground" Value="Red"/>
                    <Setter Property="ToolTip" Value="This criteria will not be applied" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGrid.CellStyle>
    

    The Style above is based on the default style for DataGridCell on Windows 10. I've only added your trigger. You may of course edit is as per your exact requirements.