如何使DataTemplate.DataTrigger检查大于或小于?

56
以下使年龄显示为红色,如果它等于 30。
如何使年龄显示为红色,如果它大于 30?
<DataTemplate DataType="{x:Type local:Customer}">
    <Grid x:Name="MainGrid" Style="{StaticResource customerGridMainStyle}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition Width="150"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Column="0" Grid.Row="0" Text="First Name" Margin="5"/>
        <TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding FirstName}" Margin="5"/>
        <TextBlock Grid.Column="0" Grid.Row="1" Text="Last Name" Margin="5"/>
        <TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding LastName}" Margin="5"/>
        <TextBlock Grid.Column="0" Grid.Row="2" Text="Age" Margin="5"/>
        <TextBlock x:Name="Age" Grid.Column="1" Grid.Row="2" Text="{Binding Age}" Margin="5"/>
    </Grid>

    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Path=Age}">
            <DataTrigger.Value>30</DataTrigger.Value>
            <Setter TargetName="Age" Property="Foreground" Value="Red"/> 
        </DataTrigger>
    </DataTemplate.Triggers>

</DataTemplate>
4个回答

86

您可以创建一个 IValueConverter,根据 CutOff 将整数转换为布尔值。然后使用 DataTrigger.ValueTrue(或False,具体取决于您的返回值)。

如果我没记错的话,WPF DataTrigger 只是严格的等式比较器。

因此,类似于以下内容:

public class CutoffConverter : IValueConverter {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        return ((int)value) > Cutoff;
    }

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

    public int Cutoff { get; set; }
}

接下来使用以下的XAML代码。

<Window.Resources>
    <myNamespace:CutoffConverter x:Key="AgeConverter" Cutoff="30" />
</Window.Resources>

<DataTemplate.Triggers>
    <DataTrigger Binding="{Binding Path=Age,
                                   Converter={StaticResource AgeConverter}}">
        <DataTrigger.Value>true</DataTrigger.Value>
        <Setter TargetName="Age" Property="Foreground" Value="Red"/> 
    </DataTrigger>
</DataTemplate.Triggers>

21
如果需要针对不同的触发器使用不同的截断值,您可以使用 ConverterParameter 来传递该值: Binding="{Binding Path=Age, Converter={StaticResource AgeConverter}, ConverterParameter=30}" - Denis Troller

11

我建议使用一个 IValueConverter 来绑定到年龄 TextBlockForeground 元素,并将着色逻辑隔离在那里。

<TextBlock x:Name="Age"  
           Text="{Binding Age}" 
           Foreground="{Binding Path=Age, Converter={StaticResource AgeToColorConverter}}" />

然后在代码中:

[ValueConversion(typeof(int), typeof(Brush))]
public class AgeToColorConverter : IValueConverter
{
   public object Convert(object value, Type target)
   {
      int age;
      Int32.TryParse(value.ToString(), age);
      return (age >= 30 ? Brushes.Red : Brushes.Black);
   }
}

9
我相信使用MVVM和INotifyPropertyChanged的功能可以更简单地实现目标。
通过 Age 属性创建另一个名为 IsAgeValid 的布尔属性。 IsAgeValid 将只是一个按需检查,在技术上来说不需要调用 OnNotify。如何做到呢?
为了将更改推送到Xaml,请在 Age setter 中触发 OnNotifyPropertyChanged 事件,以便为 IsAgeValid 内部添加此代码。
对于任何绑定到 IsAgeValid 的内容,每当订阅 Age 更改时都会发送通知消息;这正是所关注的内容……
设置完成后,根据 IsAgeValid 的结果相应地绑定样式触发器的 false 和 true。
public bool IsAgeValid{ get { return Age > 30; } }

public int Age
{ 
  get { return _Age; }

  set
  {
   _Age=value;
   OnPropertyChanged("Age");   
   OnPropertyChanged("IsAgeValid"); // When age changes, so does the
                                    // question *is age valid* changes. So 
                                    // update the controls dependent on it.
   } 
 }

2
这应该是针对特定示例的答案。在可能的情况下,代表真实业务逻辑的控件属性应通过ViewModel提供给视图,而不是“视图端”。这允许通过配置/数据库等来配置值。 - Tom Deloford
@TomDeloford 在虚拟机上拥有业务逻辑,对我来说也是有意义的。 - ΩmegaMan

1
如果可能的话,您可以向您的模型添加一个属性,这是最简单的方法。例如:
public int AgeBoundry
{
    get
    {
        if (Age < 30)
            return 0;
        else if (Age == 30)
            return 1;
        else
            return 2;
    }
}

然后您可以检查整数的值。
<DataTemplate.Triggers>
    <DataTrigger Binding="{Binding Path=Age}">
        <DataTrigger.Value>0</DataTrigger.Value>
        <Setter TargetName="Age" Property="Foreground" Value="Green"/> 
    </DataTrigger>
    <DataTrigger Binding="{Binding Path=Age}">
        <DataTrigger.Value>1</DataTrigger.Value>
        <Setter TargetName="Age" Property="Foreground" Value="Orange"/> 
    </DataTrigger>
    <DataTrigger Binding="{Binding Path=Age}">
        <DataTrigger.Value>2</DataTrigger.Value>
        <Setter TargetName="Age" Property="Foreground" Value="Red"/> 
    </DataTrigger>
</DataTemplate.Triggers>

4
触发器何时开始使用“Ageboundry”?与其绑定到“Age”,不应该是“AgeBoundary”吗? - ΩmegaMan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接