在WPF中重用Trigger Conditions或MultiBinding

时间:2012-05-15 18:07:16

标签: c# .net wpf binding controltemplate

目标是在各个地方重复使用此MultiBinding

<MultiTrigger.Conditions>
    <Condition Value="True">
        <Condition.Binding>
                <MultiBinding Converter="{StaticResource ValidationBooleanConverter}">
                    <Binding X" />
                    <Binding Y" />
                    <Binding Z" />        
                </MultiBinding>
        </Condition.Binding>
    </Condition>
</MultiTrigger.Conditions>

当前不是DRY条件(n +)

<Style x:Key="AnErrorTemplate" TargetType="FrameworkElement">
 <Style.Triggers>
    <MultiTrigger>
         <!-- Repeating the whole MultiTrigger.Conditions block here ---> 
         <Setter Property="Validation.ErrorTemplate" Value="{StaticResource DirtyErrorControlTemplate}" />
    </MultiTrigger>
 </Style.Triggers>

<Style x:Key="AnotherStyle" TargetType="FrameworkElement">
 <Style.Triggers>
    <MultiTrigger>
         <!-- Repeating the whole MultiTrigger.Conditions block here ---> 
         <Setter Property="Other" Value="SomeValueIfTheSameConditionsAreTrue" />
    </MultiTrigger>
 </Style.Triggers>

事实上,要求更广泛,因为我还需要在ControlTemplates中重用这些相同的条件。

<ControlTemplate x:Key="InlineErrorControlTemplate" TargetType="{x:Type Control}">
    <TextBlock Text="{Binding ElementName=InputView, Path=(Validation.Errors)[0].ErrorContent}" Foreground="Red"/>
     <ControlTemplate.Triggers>
         <MultiTrigger>
            <!-- Repeating the whole MultiTrigger.Conditions block here ---> 
            <Setter Property="Visibility" Value="SetMeIfTheseSameTriggerConditionsHold" />
        </MultiTrigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

易于维护的雨伞?

我是如何才能指定MultiTrigger.Conditions或MultiBinding一次,然后在多个样式和控件模板中使用它?

  • 仅限XAML?

2 个答案:

答案 0 :(得分:2)

我曾经多次遇到这种情况,我希望重用常用的绑定来设置转换器,转换器中的验证规则,通知源/目标更新等,方法是继承Binding并通过指定重用它们: / p>

Foreground="{b:CustomColorBinding CustomDateTime}"

减少我需要为绑定键入的XAML数量,但不相信有办法在XAML中保留所有内容。试图设置x:Key并使用它,就像不可能使用静态或动态资源一样。我已经习惯于使用这个约定,我为我的项目创建了一个BindingCatalog,用于存储绑定到不同类型的不同控件的常见(多)绑定方案。

我确信你有充分的理由想要避免代码隐藏,但是如果你可以在代码中创建一次MultiBinding并重复使用它来干掉你的XAML - 那么我认为它不仅仅是为了证明(过度妖魔化) ,恕我直言)将要求这样做的代码。

希望有助于决定做什么!

扩展绑定

namespace MyNamespace
{
    public class CustomBinding : Binding
    {
        public CustomBinding(String path)
            : base(path)
        {
            this.Converter = new CustomValueConverter();
            this.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            this.ValidatesOnDataErrors = true;
        }
    }
}

其XAML用法

<UserControl x:Class="MyNamespace.UserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:MyNamespace">
    <StackPanel>
        <TextBox Text="{local:CustomBinding MyViewModelProperty}"/>
    </StackPanel>
</UserControl>

答案 1 :(得分:2)

这正是WPF中提供Style inheritance的原因。另外,在您的情况下,我建议DataTrigger使用MultiBinding代替MultiTrigger代替MultiBinding ...

为了演示这一点,我们假设我正在创建一种样式,用于检查分配给任何Tooltip的{​​{1}}或Name是否为空。如果是,如果FrameworkElementForeground,则会FrameworkElement为红色;如果ComboBoxBackground,则会FrameworkElement为黄色。< / p>

我正在使用TextBox的其他字段Tag ....

因此,所有XAML(加上C#转换器)的解决方案如下......

FrameworkElement

C#转换器:

<Window x:Class="WpfApplication1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Height="300" Width="300">
    <Window.Resources>
        <local:AtleastOneEmptyConverter x:Key="AtleastOneEmptyConverter"/>
        <Style x:Key="BaseFrameworkElementStyle"
               TargetType="{x:Type FrameworkElement}">
            <Style.Triggers>
                <DataTrigger Value="True">
                    <DataTrigger.Binding>
                      <MultiBinding
                      Converter="{StaticResource AtleastOneEmptyConverter}">
                            <Binding Path="ToolTip"
                                     RelativeSource="{RelativeSource Self}"/>
                            <Binding Path="Name"
                                     RelativeSource="{RelativeSource Self}"/>
                        </MultiBinding>
                    </DataTrigger.Binding>
                    <Setter Property="Tag" Value="1"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>

        <Style x:Key="ApplyToComboStyle"
               TargetType="{x:Type ComboBox}"
               BasedOn="{StaticResource BaseFrameworkElementStyle}">
            <Style.Triggers>
                <DataTrigger
                    Binding="{Binding Tag,
                            RelativeSource={RelativeSource Self}}" Value="1">
                    <Setter Property="Foreground" Value="Red"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>

        <Style x:Key="ApplyToTextBoxStyle"
               TargetType="{x:Type TextBox}"
               BasedOn="{StaticResource BaseFrameworkElementStyle}">
            <Style.Triggers>
                <DataTrigger
                    Binding="{Binding Tag,
                            RelativeSource={RelativeSource Self}}" Value="1">
                    <Setter Property="Background" Value="Yellow"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel>
        <ComboBox Style="{StaticResource ApplyToComboStyle}"
                  x:Name="NotRedComboBox"
                  ToolTip="You will not see red text here">
            <ComboBoxItem IsSelected="True">I am not Red!</ComboBoxItem>
        </ComboBox>
        <ComboBox Style="{StaticResource ApplyToComboStyle}">
            <ComboBoxItem IsSelected="True">I am Red!</ComboBoxItem>
        </ComboBox>
        <Separator Margin="5"/>
        <TextBox Style="{StaticResource ApplyToTextBoxStyle}"
                 Text="I am yellow"
                 x:Name="YellowTextBox"/>
        <TextBox Style="{StaticResource ApplyToTextBoxStyle}"
                 Text="I am not yellow"
                 x:Name="NotYellowTextBox"
                 ToolTip="You will not see yellow background here"/>
    </StackPanel>
</Window>