【问题标题】:WPF One DataTrigger with multiple ValuesWPF 一个具有多个值的 DataTrigger
【发布时间】:2018-04-09 06:48:24
【问题描述】:

我的 WPF 窗口上有一个 Slider 和一个 TextBlock。 TextBlock 需要通过滑块的值、范围来改变背景、前景和字体大小。

我构建了一个转换器,它接收滑块的值并为每个组返回 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>

【问题讨论】:

  • 开箱即用,您可以将转换后的值分配给 TextBlock 的 Tag 属性,并在 Tag 上有多个触发器。但是,我认为多次调用转换器根本不是问题。
  • 怎么样。创建基本样式。然后三个基于三个州。使用转换器绑定样式会返回适当的样式。

标签: wpf styles converter datatrigger


【解决方案1】:

好吧,正如 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>

【讨论】:

  • 感谢 Seb 和 Clemens。很好的解决方案!
【解决方案2】:

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

这利用了一个非常令人困惑且记录不充分的功能,该功能在here 进行了讨论,并在阅读答案时把我搞糊涂了。

明确一点:我不明白为什么这里的 TARGETTYPETextBlock,当我们清楚地使用 Label 并讨论了答案时在上面的链接中。这与 valueconverter 返回一个 DOUBLE 的事实有关,它使用 TEXTBLOCK 样式处理,而 LABEL style 将被忽略。我测试了一下……

【讨论】:

    猜你喜欢
    • 2012-04-29
    • 2019-07-05
    • 1970-01-01
    • 2010-11-26
    • 2015-01-22
    • 1970-01-01
    • 2013-06-04
    • 2015-04-22
    • 1970-01-01
    相关资源
    最近更新 更多