web-dev-qa-db-ja.com

WPF:1つのバインディングで2つのコンバーターを使用する方法?

ブール値に応じて、表示/非表示にするコントロールがあります。

NegatedBooleanConverterがあり(trueからfalseに、またはその逆に切り替えます)、このコンバーターを最初に実行する必要があります。 BooleanToVisibilityConverterがあり、NegatedBoolConverterの後にこのコンバーターを実行する必要があります。

この問題を解決するにはどうすればよいですか? XAMLでこれを実行したいと思います。

編集: これは可能な解決策です。

それはうまくいかないようです。最初に別のコンバーターで値を変換し、次に変換された値で何かを行います。

私が必要なのは:

  • 最初のコンバーターで値を変換します(これにより、convertedValueが得られます)。
  • 2番目のコンバーターでConvertedValueを変換すると、この結果が必要になります。
42
Natrium

私自身の質問にもう一度答えます:私はこのソリューションを何年も使用しています: http://www.codeproject.com/Articles/15061/Piping-Value-Converters-in-WPF

最初のコンバーターを最初に呼び出し、次に2番目のコンバーターを呼び出すなど、2つの既存のコンバーターの新しいコンバーターを作成します。

私はこの解決策にかなり満足しています。

1
Natrium

これは私がやったことです:

public class CombiningConverter : IValueConverter
    {
        public IValueConverter Converter1 { get; set; }
        public IValueConverter Converter2 { get; set; }

        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            object convertedValue = Converter1.Convert(value, targetType, parameter, culture);
            return Converter2.Convert(convertedValue, targetType, parameter, culture);
        }

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

        #endregion
    }

そして私はそれをこのように呼びます:

<converters:CombiningConverter x:Key="negatedBoolToVisibilityConverter" Converter1="{StaticResource NegatedBooleanConverter}" Converter2="{StaticResource BoolToVisibilityConverter}" />

MultiValueConverterも可能だと思います。多分後で試してみるよ。

59
Natrium

ナトリウムの素晴らしい答えを拡張しています...

XAML

<conv:ConverterChain x:Key="convBoolToInverseToVisibility">
    <conv:BoolToInverseConverter />
    <BooleanToVisibilityConverter />
</conv:ConverterChain>

クラス

/// <summary>Represents a chain of <see cref="IValueConverter"/>s to be executed in succession.</summary>
[ContentProperty("Converters")]
[ContentWrapper(typeof(ValueConverterCollection))]
public class ConverterChain : IValueConverter
{
    private readonly ValueConverterCollection _converters= new ValueConverterCollection();

    /// <summary>Gets the converters to execute.</summary>
    public ValueConverterCollection Converters
    {
        get { return _converters; }
    }

    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return Converters
            .Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameter, culture));
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return Converters
            .Reverse()
            .Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameter, culture));
    }

    #endregion
}

/// <summary>Represents a collection of <see cref="IValueConverter"/>s.</summary>
public sealed class ValueConverterCollection : Collection<IValueConverter> { }
28
Jake Berger

この場合、コンバータチェーンは必要ありません。構成可能なコンバーターが必要なだけです。これは上記のCarloの回答に似ていますが、true値とfalse値を明示的に定義します(つまり、非表示、表示、または折りたたみの変換に同じコンバーターを使用できます)。

[ValueConversion(typeof(bool), typeof(Visibility))]
public class BoolToVisibilityConverter : IValueConverter
{
    public Visibility TrueValue { get; set; }
    public Visibility FalseValue { get; set; }

    public BoolToVisibilityConverter()
    {
        // set defaults
        FalseValue = Visibility.Hidden;
        TrueValue = Visibility.Visible;
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (bool)value ? TrueValue : FalseValue;
    }

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

次にXAMLで:

    <BoolToVisibilityConverter x:Key="BoolToVisibleConverter"
                               FalseValue="Hidden"
                               TrueValue="Visible" />
3
metao

プロジェクトで行うことは、通常のBooleanToVisibilityConverterを作成することです。コンバーターは1つのパラメーター(何でも、文字列、int、boolなど)を取ります。パラメータが設定されている場合は結果を反転し、設定されていない場合は通常の結果を出力します。

public class BooleanToVisibilityConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        bool? isVisible = value as bool?;
        if (parameter != null && isVisible.HasValue)
            isVisible = !isVisible;
        if (isVisible.HasValue && isVisible.Value == true)
            return Visibility.Visible;
        else
            return Visibility.Collapsed;
    }

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

    #endregion
}
3
Carlo

ここでは、2つの個別のコンバーターの代わりにマルチコンバーターを使用することをお勧めします。既存のコンバーターからロジックを再利用できるはずです。まずは このディスカッション をチェックしてください。

0
Scott Lawrence

私は、ReversedBooleanToVisibilityConverterと呼ばれるものを作成し、基本的にこれら2つがあなたのために行うことを1つのステップで実行しました。

0

この特定の問題に対処するには、2つのコンバーターを使用する代わりに、ConverterParameterを(ブール値として)使用して独自のBoolToVisibilityConverterを記述し、元のブール値を無効にするかどうかを決定します。

0
John Myczek

個人的には、完全な変換を行う単一のコンバーターを1つだけ作成します。他の場所で(否定などの)コンバーターを必死に必要としない限り、変換が1か所で1か所で行われると(imo)を維持するのが簡単になります。

0
Alastair Pitts