Search code examples
c#xamlstylesdatatrigger

How do I use a pre-defined style in a DataTrigger


In my project, I have multiple different controls that are mandatory. In order for the user to know that a field is required, I set a red outline on the field using a DataTrigger.

Here is a TextBox that is a required field:

<TextBox Text="{Binding RationaleForNoInvestigation, UpdateSourceTrigger=PropertyChanged}">
              <TextBox.Style>
                <Style TargetType="TextBox">
                  <Style.Triggers>
                    <DataTrigger Binding="{Binding RationaleForNoInvestigation, 
Converter={StaticResource IsNullOrEmptyStringConverter}}"
                                 Value="True">
                      <Setter Property="BorderBrush"
                              Value="Red" />
                      <Setter Property="BorderThickness"
                              Value="1" />
                    </DataTrigger>
                  </Style.Triggers>
                </Style>
              </TextBox.Style>
            </TextBox>

And here is a combobox that is a required field:

<telerik:RadComboBox SelectedItem="{Binding Path=SelectedRoomType, Mode=TwoWay}">
    <telerik:RadComboBox.Style>
      <Style TargetType="telerik:RadComboBox">
        <Style.Triggers>
          <DataTrigger Binding="{Binding Path=SelectedRoomType,
 Converter={StaticResource IsNullConverter}}"
                       Value="True">
            <Setter Property="BorderBrush"
                    Value="Red" />
            <Setter Property="BorderThickness"
                    Value="2" />
          </DataTrigger>
        </Style.Triggers>
      </Style>
    </telerik:RadComboBox.Style>
  </telerik:RadComboBox>

However, I may one day decide to change the visual indication of a required field, say to a blue background instead. I don't want to have to go through all the places in my project that use the style and manually change it. Instead I want to set a global style that I can reference in specific controls, and then be able to change the global style in one place.

How can I pull out these lines from the above code and be in a global place? And how would I reference it in the above TextBox and ComboBox?

<Setter Property="BorderBrush"
                          Value="Red" />
<Setter Property="BorderThickness"
                          Value="1" />

Solution

  • You can create a separate XAML file containing all your styles!

    As you need to target multiple controls, I suggest creating a different style for each one of them, since you might want to change different properties. It would look like this:

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    
        <converters:IsNullConverter x:Key="IsNullOrEmptyStringConverter" />
    
        <!-- I also highly recommend creating the color brush separately, since this enables you to change the color without changing each one of the styles --> 
        <SolidColorBrush Color="Red" x:Key="ErrorBrush" /> 
    
        <Style x:Key="ValidateTextBoxStyle" TargetType="TextBox">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Text, Source={RelativeSource AncestorType=TextBox}, Converter={StaticResource IsNullOrEmptyStringConverter}}" Value="True">
                    <Setter Property="BorderBrush" Value="{StaticResouce ErrorBrush}" />
                    <Setter Property="BorderThickness" Value="1" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    
    </ResourceDictionary> 
    

    You can reference this file in your view's XAML, like this:

    <MainView.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Styles.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </MainView.Resources>
    

    This way, you can reference your styles anywhere in your application, if you reference the Styles XAML!

    <TextBox 
        Text="{Binding RationaleForNoInvestigation, UpdateSourceTrigger=PropertyChanged}" 
        Style="{StaticResource ValidateTextBoxStyle}
        />