DependencyProperty CoerceValueCallback与泛型

时间:2016-11-21 15:44:14

标签: c# wpf generics dependency-properties

我正在构建一个使用DependencyProperty和泛型的wpf控件,我需要(至少我认为)CoerceValueCallback来检查值是否正确。 我的想法是构建一个基类,我将从中派生出数字类型。

public abstract class MyClass<T> : Control where T : struct, IComparable
{

    public T MinValue { get; set; }
    public T MaxValue { get; set; }

    public T Value
    {
        get { return (T)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    // DependencyProperty as the backing store for Value
    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
        "Value",
        typeof(T),
        typeof(MyClass<T>),
        new PropertyMetadata(default(T), null, CoerceValue)
    );


    private static object CoerceValue(DependencyObject d, object baseValue)
    {
        T value = (T)baseValue;
        ((MyClass<T>)d).CoerceValueToBounds(ref value);

        return value;
    }

    private void CoerceValueToBounds(ref T value)
    {
        if (value.CompareTo(MinValue) < 0)
            value = MinValue;
        else if (value.CompareTo(MaxValue) > 0)
            value = MaxValue;
    }
}

问题是CoerceValue正在返回一个对象而我找不到如何返回泛型。

有什么想法吗?

编辑:由于以下答案,我在这里做了

{{1}}

这样,我可以在MinValue和MaxValue中限制Value并使用generic保持一切,从而避免覆盖每个派生类中的抽象方法。

2 个答案:

答案 0 :(得分:1)

添加如下的抽象CoerceValue方法:

public abstract class MyClass<T> : Control where T : struct
{
    ...

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
        "Value", typeof(T), typeof(MyClass<T>),
        new PropertyMetadata(default(T), null, CoerceValue));

    protected abstract T CoerceValue(T value);

    private static object CoerceValue(DependencyObject d, object value)
    {
        return ((MyClass<T>)d).CoerceValue((T)value);
    }
}

public class MyDerivedClass : MyClass<int>
{
    protected override int CoerceValue(int value)
    {
        return Math.Max(100, Math.Min(200, value));
    }
}

答案 1 :(得分:0)

虽然您的控件可以使用泛型,但在使用CoerceValueCallback时,您必须维护委托回调。 C# documentation指定委托密封。

我还注意到您的PropertyMetadata存在问题。您将传递null作为默认值。当我之前检查过null时,这让我措手不及。以下是我测试时对我有用的代码:

public class MyClass<T> : Control where T : struct
{
    public T Value
    {
        get { return (T)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    // DependencyProperty as the backing store for Value
    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
        "Value",
        typeof(T),
        typeof(MyClass<T>),
        new PropertyMetadata(default(T), null, CoerceValue) //Must pass default(T) otherwise an exception will occur.
    );

    private static object CoerceValue(DependencyObject d, object baseValue)
    {
        var tValue = (T)baseValue;
        // Check if tValue is valid 
        return tValue;
    }
}

从CoerceValue方法返回值后,必须将其强制转换为T.