0

我目前正在研究CustomConverterWPF。这就像一个通用转换。

阅读此博客,找到了一种简化 xaml 的方法。

所以转换器看起来像这样:

public CustomConverter : MarkupExtension, IMultiValueConverter {

    public ParametersCollection Parameters { get; set; }

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
        if(Parameters == null)
            return Binding.DoNothing;
        //Convertion Logic
        //...
    }
    public override object ProvideValue(IServiceProvider serviceProvider) {
        return new CustomConverter();
    }
}
public class ParametersCollection : ObservableCollection<object> {
}

在我的 Xaml 文件中,有以下内容:

<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                 xmlns:primitives="clr-namespace:System;assembly=mscorlib"
                 xmlns:converter="clr-namespace:NS.Converters">
    <Label>
        <Label.Visibility>
            <MultiBinding>
                <converter:CustomConverter>
                    <converter:CustomConverter.Parameters>
                        <converter:ParametersCollection>
                            <primitives:String>Param1</primitives:String>
                            ...
                        </converter:ParametersCollection>
                    </converter:CustomConverter.Parameters>
                </converter:CustomConverter>
            </MultiBinding>
            <!--Bindings start here -->
        </Label.Visibility>
    </Label>
</UserControl>

因此,在调试代码时,该Parameters属性为空(null),因此 xaml 不会填充集合。所以我的问题是,如何仅使用 xaml 而不使用 C# 代码来填充参数。

4

1 回答 1

0

如果你在Convert方法的第一行放置一个断点,你会发现它Parameters总是null. 那是因为你从不初始化它。解决方案是在构造函数中初始化该属性(或者在声明中初始化,如果你在 C#6 中)。

Parameters不需要是ObservableCollection<T>,因为没有人会绑定到它,它也不需要是非泛型子类。最后,ProvideValue()应提供Parameters从 XAML 获得的实际实例。如果您返回一个带有空集合的新实例Parameters,它将没有任何Parameters. ProvideValue()在创建和初始化之后调用。目的不是提供您自己的类的新实例,而是提供像StaticResourceorDynamicResource这样的标记扩展,这些扩展使用它们的参数并使用这些参数来创建或检索它们自身以外的东西的实例。

public class CustomConverter : MarkupExtension, IMultiValueConverter
{
    public CustomConverter()
    {
        Parameters = new List<Object>();
    }
    public List<Object> Parameters { get; set; }

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (Parameters == null)
            return Binding.DoNothing;

        //  Just something that returns something, for testing
        //  Replace with your own convertion logic. 
        return String.Join(";", Parameters);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        return null;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
}
于 2017-04-07T18:03:26.603 回答