首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >IValueConverter与MarkupExtension

IValueConverter与MarkupExtension
EN

Stack Overflow用户
提问于 2015-02-13 13:48:10
回答 2查看 4.5K关注 0票数 15

最近我读到了一个IValueConverter,它也是从MarkupExtension继承的。就像:

代码语言:javascript
复制
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());
    }
}

其用法看上去如下:

代码语言:javascript
复制
<Button Content="Delete" Visibility="{Binding CanDelete, UpdateSourceTrigger=PropertyChanged, Converter={local:BoolToVisibilityConverter}"/>

我习惯于使用来自资源的转换器,例如:

代码语言:javascript
复制
<loc:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
...
<Button Content="Delete" Visibility="{Binding CanDelete, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BoolToVisibilityConverter}"/>

我现在的第一个问题是:更好的方法是什么?如果我使用的是MarkupExtension-Version (除了这个用法更容易输入),它有什么好处?

我还看到了一个非常类似的实现,类似于:

代码语言:javascript
复制
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;        
    }
}

如果我正确理解它,第一个解决方案只创建这个转换器的一个实例。第二个例子为每个XAML创建一个新的这个转换器实例,对吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-02-13 14:03:45

在这种情况下,标记扩展提供的唯一(轻微)优势是更简洁的XAML语法。

而不是这样:

代码语言:javascript
复制
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
...
{Binding SomeBooleanProperty, Converter={StaticResource BooleanToVisibilityConverter}}

你可以拥有这个:

代码语言:javascript
复制
{Binding SomeBooleanProperty, Converter={my:BoolToVisibilityConverter}}

在我看来,这并不值得。如果您对保存击键感到烦恼,那么只需缩短用于引用转换器的键:

代码语言:javascript
复制
<BooleanToVisibilityConverter x:Key="btvc" />
...
{Binding SomeBooleanProperty, Converter={StaticResource my:btvc}}

由于标记扩展的ProvideValue方法是实例方法,因此只能在创建类的实例之后调用它。由于类既是标记扩展,又是转换器,所以代码的两个变体每次都会创建一个转换器。唯一的区别是,第一个变量总是返回相同的转换器:但是,它不会阻止创建另一个转换器。

票数 10
EN

Stack Overflow用户

发布于 2018-12-04 12:00:45

我从未见过在网上使用MarkupExtension的一个巨大优点是它允许您将值传递给转换器,这些值可以用作参数或返回值,例如:

代码语言:javascript
复制
public class CustomNullToVisibilityConverter : MarkupExtension, IValueConverter
{
    public object NullValue { get; set; }
    public object NotNullValue { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null) return NullValue;

        return NotNullValue;
    }

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

用法:

代码语言:javascript
复制
...
Visibility="{Binding Property, 
            Converter={cnv:CustomNullToVisibilityConverter 
                       NotNullValue=Visible, NullValue=Collapsed}}" />
...

确保引用.xaml中转换器的命名空间。

编辑:

我忘记提到的一件事是,是的,这个方法在每次使用转换器时都会创建一个新实例,这是正确的,这是一个缺点。

但是,没有什么可以阻止您将带有MarkupExtension的转换器添加到资源字典中--这样的话,它只会被安装一次。就像这样:

代码语言:javascript
复制
<cnv:CustomNullToVisibilityConverter x:Key="NullToVisibilityConverter"
        NotNullValue=Visible, NullValue=Collapsed />
...
Visibility="{Binding Property, Converter={StaticResource NullToVisibilityConverter}" />
...
票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28501091

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档