动态资源数据触发校验值

Data trigger check value of dynamic resource

我有一个 WPF 应用程序,其内容应该以德语和英语显示。因此,我创建了两个单独的资源词典,其中包含每种语言的字符串片段。当应用程序处于 运行 时,可以在语言之间切换。 在这一点上,我陷入了一个问题。用户可以进行一些设置。如果设置成功完成,则会显示一条消息。消息的文本取自资源字典。根据成功或错误消息,文本显示为绿色或红色。

<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>

要在应用程序 运行 时切换语言成为可能,从资源字典中获取的字符串片段必须是 DynamicResource。不幸的是,我不能在数据触发器中使用 DynamicResources 作为条件。有没有人遇到过类似的问题?感谢您的建议!

不要在本地化文本上使用触发器,它也不适用于 DynamicResouce,因为 Value 不是依赖项 属性,也不可读。相反,创建一个 enum 来描述您的错误。

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?
}

为错误公开另一个 属性 并在必要时实施 INotifyPropertyChanged

public ErrorType ErrorType { get; } 

使用 属性 而不是您的资源作为触发器的 Value

<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>

奖金回合。 由于您的数据触发器是重复的(它们经常设置相同的值),请考虑将 Binding 与自定义转换器一起使用,如果绑定值匹配任何给定值,应用此 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();
   }
}

在范围内的任何资源字典中创建转换器实例。

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

更改数据触发器并将数组中的目标值作为转换器参数传递。

<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>