11

最近、IValueConverterからも継承するについて読みましたMarkupExtension。それは次のようなものでした:

internal class BoolToVisibilityConverter : MarkupExtension, IValueConverter
{
    private static BoolToVisibilityConverter converter;
    public BoolToVisibilityConverter()
    {
    }
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is bool)
        {
            if ((bool)value)
            {
                return Visibility.Visible;
            }
        }
        return Visibility.Collapsed;
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is Visibility)
        {
            Visibility visibility = (Visibility)value;
            if (visibility == Visibility.Collapsed)
            {
                return false;
            }
        }
        return true;
    }
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return converter ?? (converter = new BoolToVisibilityConverter());
    }
}

使用法は次のようになります。

<Button Content="Delete" Visibility="{Binding CanDelete, UpdateSourceTrigger=PropertyChanged, Converter={local:BoolToVisibilityConverter}"/>

私は、次のような Resource からのコンバーターを使用していました。

<loc:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
...
<Button Content="Delete" Visibility="{Binding CanDelete, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BoolToVisibilityConverter}"/>

私の最初の質問は次のとおりです。より良い方法は何ですか? を使用している場合、どのような利点がありますかMarkupExtension-Version(使用法が入力しやすいことに加えて)?

次のような非常によく似た実装も見ました。

internal class BoolToVisibilityConverter : MarkupExtension, IValueConverter
{
    public BoolToVisibilityConverter()
    {
    }
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is bool)
        {
            if ((bool)value)
            {
                return Visibility.Visible;
            }
        }
        return Visibility.Collapsed;
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is Visibility)
        {
            Visibility visibility = (Visibility)value;
            if (visibility == Visibility.Collapsed)
            {
                return false;
            }
        }
        return true;
    }
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;        
    }
}

私の理解が正しければ、最初の解決策はこのコンバーターのインスタンスを 1 つだけ作成します。2 つ目は、XAML ごとにこのコンバーターの新しいインスタンスを作成しますよね?

4

2 に答える 2

9

この場合、マークアップ拡張機能が提供する唯一の (わずかな) 利点は、より簡潔な XAML 構文です。

これの代わりに:

<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
...
{Binding SomeBooleanProperty, Converter={StaticResource BooleanToVisibilityConverter}}

あなたはこれを持つことができます:

{Binding SomeBooleanProperty, Converter={my:BoolToVisibilityConverter}}

私の意見では、それは本当に価値がありません。キーストロークを節約することを気にしている場合は、コンバーターを参照するために使用されるキーを短くすることができます:

<BooleanToVisibilityConverter x:Key="btvc" />
...
{Binding SomeBooleanProperty, Converter={StaticResource my:btvc}}

ProvideValueマークアップ拡張機能のメソッドはインスタンスメソッドであるため、クラスのインスタンスが作成された後にのみ呼び出すことができます。クラスはマークアップ拡張機能とコンバーターの両方であるため、コードの両方のバリアントが毎回コンバーターを作成します。唯一の違いは、最初のバリアントが常に同じコンバーターを返すことです。ただし、別のコンバーターの作成を停止することはありません。

于 2015-02-13T14:03:45.203 に答える