【问题标题】:WPF - How to combine DataTrigger and Trigger?WPF - 如何结合 DataTrigger 和 Trigger?
【发布时间】:2010-10-10 19:00:45
【问题描述】:

注意我已经问过相关问题:How to combine DataTrigger and EventTrigger?

我有一个包含多个项目的列表框。该项目的类实现INotifyPropertyChanged 并具有属性IsAvailable。我使用该属性以不同的颜色指示列表中不可用的选项。

但是,如果所选项目不可用,则前景色应为红色。

<ListBox>
  <ListBox.Resources>
    <DataTemplate DataType="{x:Type local:InstitutionViewModel}">
      <TextBlock Name="Name" Text="{Binding Name}"/>
      <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding IsAvailable}" Value="False">
          <Setter TargetName="Name" Property="Foreground" Value="#888"/>
        </DataTrigger>
      </DataTemplate.Triggers>
    </DataTemplate>
  </ListBox.Resources>
</ListBox>

我使用上述数据触发器将不可用的项目变灰。

我面临的问题是,选择项目的事实与模板绑定到的基础数据无关。我真正想要的是某种多触发器,它支持依赖属性 (ListBoxItem.IsSelected) 上的常规 Trigger 以及绑定数据项上的 DataTrigger

如果不将选择概念引入我的视图模型,是否可以做到这一点?

对于任何想知道我为什么不禁用不可用项目的人,请了解可以选择不可用选项是应用程序的要求。实际上有几个列表框,其中一个选择会影响其他列表框的可用内容。我无法禁用这些项目,因为如果根据之前的选择禁用项目,用户将无法改变主意或探索不同的组合。

【问题讨论】:

    标签: .net wpf triggers selection listboxitem


    【解决方案1】:

    对于遇到此问题的其他人,我找到了适合我的解决方案。当然,我仍然有兴趣看到其他有趣的答案。

    这就是我所做的:

    <MultiDataTrigger>
      <MultiDataTrigger.Conditions>
        <Condition Binding="{Binding
          RelativeSource={
            RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}},
            Path=IsSelected}" Value="True"/>
        <Condition Binding="{Binding IsAvailable}" Value="False"/>
      </MultiDataTrigger.Conditions>
      <Setter TargetName="Name" Property="Foreground" Value="#F00"/>
    </MultiDataTrigger>
    

    不过,这是一个多触发器并没有什么特别之处。如果您只是想在数据模板中以不同的方式设置所选项目的样式,您可以使用:

    <DataTrigger Binding="{Binding 
      RelativeSource={
        RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}},
        Path=IsSelected}" Value="True">
      <Setter TargetName="Name" Property="Foreground" Value="#888"/>
    </DataTrigger>
    

    【讨论】:

    • 这正是我要推荐的。据我所知,这是最好的解决方案。
    • 刚刚遇到同样的问题。非常棒的家伙,忘记了相对源绑定。
    【解决方案2】:

    要将其与DataGridRow 一起使用,请将绑定模式更改为Self

    Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=... 
    

    【讨论】:

    • 此外,如果您尝试使用Path=Selector.IsSelectionActive,请改用Path=(Selector.IsSelectionActive),因为它是附加属性。
    【解决方案3】:

    对于 DevExpress GridControl,有一个 example 用于组合字段值格式条件和行 IsFocused 属性。

    XAML:

    <dxg:GridControl.View>
        <dxg:TableView CustomRowAppearance="CustomRowAppearance" NavigationStyle="Row"> 
            <dxg:TableView.FormatConditions> 
                <dxg:DataBarFormatCondition FieldName="Profit" PredefinedFormatName="GreenGradientDataBar" /> 
                <dxg:FormatCondition FieldName="Profit" Expression="[Profit]&lt;0" PredefinedFormatName="RedText"/> 
                <dxg:FormatCondition FieldName="Profit" Expression="[Profit]&gt;=0" PredefinedFormatName="GreenText"/> 
                <dxg:FormatCondition FieldName="Profit" Expression="[Profit]&lt;=0" PredefinedFormatName="LightRedFillWithDarkRedText" ApplyToRow="True"/> 
            </dxg:TableView.FormatConditions> 
        </dxg:TableView>
    </dxg:GridControl.View>
    

    C#:

    void CustomRowAppearance(object sender, CustomRowAppearanceEventArgs e) {
        if (e.RowSelectionState != SelectionState.None) {
            object result = e.ConditionalValue;
            if (e.Property == TextBlock.ForegroundProperty || e.Property == TextBlock.BackgroundProperty) {
                SolidColorBrush original = e.OriginalValue as SolidColorBrush;
                SolidColorBrush conditional = e.ConditionalValue as SolidColorBrush;
                if (conditional != null && (original == null || original.Color != conditional.Color))
                    result = ShadeBrush(conditional);
            }
            e.Result = result;
            e.Handled = true;
        }
    }
    
    SolidColorBrush ShadeBrush(SolidColorBrush brush) {
        Color originalColor = brush.Color;
        float coefficient = 0.75f;
        byte a = originalColor.A;
        if (!grid.IsKeyboardFocusWithin) // I commented this line in WPF
            a = (byte)(originalColor.A / 2);
        byte r = (byte)(originalColor.R * coefficient);
        byte g = (byte)(originalColor.G * coefficient);
        byte b = (byte)(originalColor.B * coefficient);
        return new SolidColorBrush(Color.FromArgb(a, r, g, b));
    }
    

    【讨论】:

      猜你喜欢
      • 2010-12-13
      • 2017-12-01
      • 2012-07-11
      • 2023-04-05
      • 2012-10-23
      • 2013-12-30
      • 1970-01-01
      • 2017-01-14
      • 2010-12-03
      相关资源
      最近更新 更多