Home > other >  Data trigger check value of dynamic resource
Data trigger check value of dynamic resource

Time:03-03

I have a WPF application and the content of should be displayed in German and English. Therefore, I created two seperate resource dictionaries which contain string snippets in each language. It is possible to switch between the languages while the application is running. At this point I got stuck at a problem. There are some settings the user can make. If the setting was completed successfully a message shows up. The text of the message is taken from the resource dictionary. Based on a success or error message the text is displayed green or red.

<TextBlock Text="{Binding UpdateTaxPercentageSettingsMessage}" FontWeight="Bold">
    <TextBlock.Style>
        <Style TargetType="{x:Type TextBlock}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding UpdateTaxPercentageSettingsMessage}" Value="{DynamicResource tax_percentage_update_went_wrong}">
                    <Setter Property="Foreground" Value="Red"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding UpdateTaxPercentageSettingsMessage}" Value="{StaticResource active_tax_law_update_went_wrong}">
                    <Setter Property="Foreground" Value="Red"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding UpdateTaxPercentageSettingsMessage}" Value="{StaticResource tax_percentage_was_updated_successfully}">
                    <Setter Property="Foreground" Value="Green"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding UpdateTaxPercentageSettingsMessage}" Value="{StaticResource active_tax_law_was_updated_successfully}">
                    <Setter Property="Foreground" Value="Green"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding UpdateTaxPercentageSettingsMessage}" Value="{StaticResource differential_taxation_info_update_went_wrong}">
                    <Setter Property="Foreground" Value="Red"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding UpdateTaxPercentageSettingsMessage}" Value="{StaticResource differential_taxation_info_was_updated_successfully}">
                    <Setter Property="Foreground" Value="Green"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TextBlock.Style>
</TextBlock>

To make switching languages possible while the application is running, the string snippets taken from the resource dictionary has to be a DynamicResource. Unfortunately, I can not use DynamicResources as condition in data triggers. Has anyone faced a similar problem yet? I am grateful for your suggestions!

CodePudding user response:

Do not use triggers on localized text, neither does it work with DynamicResouce, because Value is not a dependency property, nor is it readable. Instead, create an enum that describes your errors.

public enum ErrorType
{
   WhoCares, // No comment on this.
   ThisIsSuspicious, // Suspicous value.
   ItsATrap, // Admiral Ackbar warned us.
   ItIsNotWhatYouThinkItIs, // It is exactly what you think.
   ItCannotBeThatSerious, // Serious Sam approves.
   WhatDoesTheFlashingRedLightMean // If it is still flashing, how bad can it be, really?
}

Expose anothe property for the error and implement INotifyPropertyChanged if necessary.

public ErrorType ErrorType { get; } 

Use the property instead of your resources as Value of the triggers.

<TextBlock Text="{Binding UpdateTaxPercentageSettingsMessage}" FontWeight="Bold">
   <TextBlock.Style>
      <Style TargetType="{x:Type TextBlock}">
         <Style.Triggers>
            <DataTrigger Binding="{Binding ErrorType}" Value="{x:Static local:ErrorType.WhoCares}">
               <Setter Property="Foreground" Value="Red"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding ErrorType}" Value="{x:Static local:ErrorType.ThisIsSuspicious}">
               <Setter Property="Foreground" Value="Red"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding ErrorType}" Value="{x:Static local:ErrorType.ItsATrap}">
               <Setter Property="Foreground" Value="Green"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding ErrorType}" Value="{x:Static local:ErrorType.ItIsNotWhatYouThinkItIs}">
               <Setter Property="Foreground" Value="Green"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding ErrorType}" Value="{x:Static local:ErrorType.ItCannotBeThatSerious}">
               <Setter Property="Foreground" Value="Red"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding ErrorType}" Value="{x:Static local:ErrorType.WhatDoesTheFlashingRedLightMean}">
               <Setter Property="Foreground" Value="Green"/>
            </DataTrigger>
         </Style.Triggers>
      </Style>
   </TextBlock.Style>
</TextBlock>

Bonus round. As your data triggers are repetitive (they set the same values often), consider using a Binding with a custom converter that simply says, if the bound value matches any of the given values, apply this setter.

public class IsMatchingConverter : IValueConverter
{
   public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
   {
      if (!(parameter is IEnumerable enumerable))
         return false;

      return enumerable.Cast<object>().Contains(value);
   }

   public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
   {
      throw new InvalidOperationException();
   }
}

Create an instance of the converter in any resource dictionary in scope.

<Window.Resources>
   <local:IsMatchingConverter x:Key="IsMatchingConverter"/>
</Window.Resources>

Change the data triggers and pass the target values in an array as converter parameters.

<TextBlock Text="{Binding UpdateTaxPercentageSettingsMessage}" FontWeight="Bold">
   <TextBlock.Style>
      <Style TargetType="{x:Type TextBlock}">
         <Style.Triggers>
            <DataTrigger Value="True">
               <DataTrigger.Binding>
                  <Binding Path="ErrorType" Converter="{StaticResource IsMatchingConverter}">
                     <Binding.ConverterParameter>
                        <x:Array Type="local:ErrorType">
                           <local:ErrorType>WhoCares</local:ErrorType>
                           <local:ErrorType>ThisIsSuspicious</local:ErrorType>
                           <local:ErrorType>ItCannotBeThatSerious</local:ErrorType>
                        </x:Array>
                     </Binding.ConverterParameter>
                  </Binding>
               </DataTrigger.Binding>
               <Setter Property="Foreground" Value="Red"/>
            </DataTrigger>
            <DataTrigger Value="True">
               <DataTrigger.Binding>
                  <Binding Path="ErrorType" Converter="{StaticResource IsMatchingConverter}">
                     <Binding.ConverterParameter>
                        <x:Array Type="local:ErrorType">
                           <local:ErrorType>ItsATrap</local:ErrorType>
                           <local:ErrorType>ItIsNotWhatYouThinkItIs</local:ErrorType>
                           <local:ErrorType>WhatDoesTheFlashingRedLightMean</local:ErrorType>
                        </x:Array>
                     </Binding.ConverterParameter>
                  </Binding>
               </DataTrigger.Binding>
               <Setter Property="Foreground" Value="Green"/>
            </DataTrigger>
         </Style.Triggers>
      </Style>
   </TextBlock.Style>
</TextBlock>
  • Related