2

目的は、この MultiBinding をさまざまな場所で再利用することです

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

現在、あまり乾燥していない状態 (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 のみですか?
4

2 に答える 2

3

Style inheritanceが WPF で提供されたのはまさにそのためです。さらに、あなたの場合、 with の代わりに with を使用することをおDataTrigger勧めMultiBindingMultiTriggerますMultiBinding...

Tooltipこれを実証するために、またはNameに割り当てられたFrameworkElementが空であるかどうかをチェックするスタイルを作成していると仮定します。その場合、が のForeground場合は赤になり、 が の場合は黄色になります。FrameworkElementComboBoxBackgroundFrameworkElementTextBox

...の雑多なフィールドTagを使用しています。FrameworkElement

したがって、これに対するすべての XAML (および 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>

C# コンバーター:

public class AtleastOneEmptyConverter : IMultiValueConverter
{
    public object Convert
        (object[] values, Type targetType,
         object parameter, CultureInfo culture)
    {
        return values.Cast<string>().Any(val => string.IsNullOrEmpty(val));
    }

    public object[] ConvertBack
        (object value, Type[] targetTypes,
        object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
于 2012-05-16T08:03:17.967 に答える
2

私は何度もこの状況に陥り、コンバーターを設定する一般的に使用されるバインディング、それらのコンバーター内の検証ルール、ソース/ターゲットの更新の通知などを、バインディングから継承し、指定して再利用することで再利用したいと考えています。

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>
于 2012-05-16T03:52:12.483 に答える