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 并且在阅读答案时让我感到困惑。
明确一点:我不明白为什么这里的 TARGETTYPE 是 TextBlock,而我们显然使用 Label,答案在上面的link中讨论过。它与以下事实有关 valueconverter returns a DOUBLE,它被 TEXTBLOCK 样式,而 LABEL 样式将被忽略。我用艰难的方式测试了它...
我的 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 并且在阅读答案时让我感到困惑。
明确一点:我不明白为什么这里的 TARGETTYPE 是 TextBlock,而我们显然使用 Label,答案在上面的link中讨论过。它与以下事实有关 valueconverter returns a DOUBLE,它被 TEXTBLOCK 样式,而 LABEL 样式将被忽略。我用艰难的方式测试了它...