为自定义控件创建依赖项属性

时间:2015-03-17 20:41:11

标签: c# wpf dependency-properties

我正在尝试为自定义DependencyProperty创建Control

我希望能够设置一个FileList属性,该属性将设置为字符串,以逗号分隔,但作为字符串列表存储在内存中。

这是我到目前为止所拥有的:

public class FileTypeListControl : Control 
{
    public static readonly DependencyProperty FileTypeListProperty
        = DependencyProperty.Register(
            "FileTypeList",
            typeof(List<string>),
            typeof(FileTypeListControl),
            new PropertyMetadata(new List<string>() { ".txt" },
                OnFileTypeListPropertyChanged,
                OnCoerceFileTypeListProperty),
                OnValidateFileTypeListPropety);  

    public List<string> FileTypeList
    {
        get
        {
            return (List<string>)GetValue(FileTypeListProperty);
        }
        set
        {
            SetValue(FileTypeListProperty, value);
        }
    }

    public static void OnFileTypeListPropertyChanged(
        DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
    }

    public static object OnCoerceFileTypeListProperty(
        DependencyObject sender, object data)
    {
        if (data is string)
        {
            var val = (data as string).Split(new char[] { ',' });
            return val;
        }
        else if (data is List<string>)
        {
            return data;
        }
        else
        {
            return new List<string>();
        }
    }

    public static bool OnValidateFileTypeListPropety(object data)
    {
        return true;
    }
}


<local:FileTypeListControl x:Name="control"
                           Grid.Column="2"
                           FileTypeList=".xml,.java,.exe"/>

现在,问题在于它不像我在xaml中指定FileTypeList属性的方式。我的印象是OnCoerceFileListProperty方法将值强制转换为合适的类型,这就是我正在做的事情。

我可以使用值转换器,但每次我想重新使用控件时,这都不正确。

我在这里做错了什么?

1 个答案:

答案 0 :(得分:1)

CoerceValueCallback的目的不是执行类型转换。此任务通常由TypeConverters执行,如下所示:

public class StringListConverter : TypeConverter
{
    public override bool CanConvertFrom(
        ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string);
    }

    public override object ConvertFrom(
        ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        return ((string)value).Split(',');
    }
}

...

[TypeConverter(typeof(StringListConverter))]
public IList<string> FileTypeList
{
    get { return (IList<string>)GetValue(FileTypeListProperty); }
    set { SetValue(FileTypeListProperty, value); }
}

另请注意,将该属性声明为IList<string>可提供比List<string>更大的灵活性。

您还应该避免使用类似new List<string>() { ".txt" }的表达式作为依赖项属性的默认值,因为此值用于属性的所有“实例”。当你例如在一个控件实例中向FileTypeList属性添加一个字符串,只要它们具有默认属性值,此更改也将在其他控件实例中进行。

对于所有引用类型属性,默认值应为null。然后,您可以在控件的构造函数中设置实际默认值:

public FileTypeListControl()
{
    SetCurrentValue(FileTypeListProperty, new List<string>() { ".txt" });
}