xaml 上的 ObservableCollection<T>

ObservableCollection<T> on xaml

我目前正在 WPF 上开发 CustomConverter。这就像一个通用转换。

阅读此 blog,找到了一种简化 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# 代码来填充参数。

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

Parameters 不需要是 ObservableCollection<T>,因为没有人会绑定到它,它也不需要是非通用子 class。最后,ProvideValue() 应该提供具有从 XAML 中获得的 Parameters 的实际实例。如果您 return 一个带有空 Parameters 集合的新实例,它将没有任何 ParametersProvideValue() 在您创建并初始化后调用。目的不是提供您自己的 class 的新实例,而是用于像 StaticResourceDynamicResource 这样的标记扩展,它们采用它们的参数并使用这些参数来创建或检索某物的实例除了他们自己。

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;
    }
}