我正在构建一个使用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保持一切,从而避免覆盖每个派生类中的抽象方法。
答案 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.