WPF 一个具有多个值的 DataTrigger

WPF One DataTrigger with multiple Values

我的 WPF window 上有一个 Slider 和一个 TextBlock。 TextBlock 需要通过滑块的值,通过 rang 来改变背景,前景和字体大小。

我构建了一个转换器,它接收滑块的值和 returns 每个组的 0、1 或 3。

public class ValueByRange : IValueConverter
{
    public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double.TryParse(value?.ToString(), out double dValue);

        if (dValue > 80)
            return 2;
        else if (dValue > 50)
            return 1;

        return 0;
    }
    public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return false;
    }
}

我的 TextBlock 看起来像这样:

<TextBlock Width="30" Text="{Binding ElementName= theSlider, Path=Value}">
        <TextBlock.Style>
            <Style TargetType="TextBlock">
                <Setter Property="Background" Value="Transparent"/>
                <Setter Property="Foreground" Value="Black"/>
                <Setter Property="FontSize" Value="12"/>
                <Setter Property="TextAlignment" Value="Center"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding ElementName=theSlider, Path=Value, Converter={StaticResource ValueByRange}}" Value="1">
                        <Setter Property="Background" Value="Yellow"/>
                        <Setter Property="Foreground" Value="Black"/>
                        <Setter Property="FontSize" Value="14"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding ElementName=theSlider, Path=Value, Converter={StaticResource ValueByRange}}" Value="2">
                        <Setter Property="Background" Value="Red"/>
                        <Setter Property="Foreground" Value="White"/>
                        <Setter Property="FontSize" Value="16"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
</TextBlock>

它工作正常,但感觉不是最好的方法。转换器触发 2 次,每次针对每个 DataTrigger。我需要超过这 3 个范围,这意味着转换器将触发更多次。 出于同样的原因,为每个 属性 构建一个转换器也没有帮助。

有没有办法只触发转换器然后检查结果(不使用其他代码)?

我知道这不是正确的语法,但我的意思是这样的:

<DataTrigger Binding="{Binding ElementName=theSlider, Path=Value, Converter={StaticResource ValueByRange}}">
    <DataTrigger.Value Value ="1">
        <Setter Property="Background" Value="Yellow" />
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="FontSize" Value="14" />
    </DataTrigger.Value>
    <DataTrigger.Value Value ="2">
        <Setter Property="Background" Value="Red" />
        <Setter Property="Foreground" Value="White" />
        <Setter Property="FontSize" Value="16" />
    </DataTrigger.Value>
</DataTrigger>

好吧,正如 Clemens 所说,多次调用转换器并没有错。

但如果您真的想这样做,这里有一个可行的方法:

<Grid>
    <Grid.Resources>

        <local:ValueByRange x:Key="ValueByRange" />

        <Style x:Key="TextBlockInLabelStyle" TargetType="TextBlock">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="Foreground" Value="Black"/>
            <Setter Property="FontSize" Value="12"/>
            <Setter Property="TextAlignment" Value="Center"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding}" Value="1">
                    <Setter Property="Background" Value="Yellow"/>
                    <Setter Property="Foreground" Value="Black"/>
                    <Setter Property="FontSize" Value="14"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding}" Value="2">
                    <Setter Property="Background" Value="Red"/>
                    <Setter Property="Foreground" Value="White"/>
                    <Setter Property="FontSize" Value="16"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>

    </Grid.Resources>

    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>

    <Slider Grid.Row="0"
            x:Name="Slider1" 
            Interval="1" 
            Minimum="0" 
            Maximum="100" />

    <Slider Grid.Row="1" 
            x:Name="Slider2" 
            Interval="1" 
            Minimum="0" 
            Maximum="100" />

    <Label Grid.Row="2" Content="{Binding ElementName=Slider1, Path=Value, Converter={StaticResource ValueByRange}}">
        <Label.Resources>
            <Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource TextBlockInLabelStyle}" />
        </Label.Resources>
    </Label>

    <Label Grid.Row="3" Content="{Binding ElementName=Slider2, Path=Value, Converter={StaticResource ValueByRange}}">
        <Label.Resources>
            <Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource TextBlockInLabelStyle}" />
        </Label.Resources>
    </Label>
</Grid>

我想对上面的答案做个注释:

这利用了一个非常令人困惑且记录不完整的功能,该功能已被讨论 here 并且在阅读答案时让我感到困惑。

明确一点:我不明白为什么这里的 TARGETTYPETextBlock,而我们显然使用 Label,答案在上面的link中讨论过。它与以下事实有关 valueconverter returns a DOUBLE,它被 TEXTBLOCK 样式,而 LABEL 样式将被忽略。我用艰难的方式测试了它...