我有一个源自通用基础的WPF控件。 例如:来自UpDownBase的NumericUpDown的CommonNumericUpDown中的IntegerUpDown。
UpDownBase有一个声明为:
的静态属性public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( "Value", typeof( T ), typeof( UpDownBase<T> ), new FrameworkPropertyMetadata( default( T ), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValueChanged, OnCoerceValue, false, UpdateSourceTrigger.LostFocus ) );
我收到以下异常:
TypeLoadException(GenericArguments [0],'System.Nullable 1[T]', on 'System.Nullable
1 [T]'违反了类型参数'T'的约束。)
当我尝试(当'动态'试图获得'ValueProperty'时发生异常):
var frameWorkElement = e.OriginalSource as FrameworkElement;
while (frameWorkElement != null)
{
if (IsSubclassOfRawGeneric(typeof(UpDownBase<>), frameWorkElement.GetType())) // JaredPar StackOverfLow code
{
dynamic upDownT = frameWorkElement;
DependencyProperty dp = upDownT.ValueProperty; // TypeLoadException
if (dp != null)
{
be = frameWorkElement.GetBindingExpression(dp);
if (be != null)
{
be.UpdateSource();
}
}
break;
}
frameWorkElement = VisualTreeHelper.GetParent(frameWorkElement) as FrameworkElement;
}
为什么我会收到该异常,如何以通用方式从我的对象中获取相应的dependencyProperty(没有切换案例或类似的东西)?
更新
我修改了JaredPar代码以获取类型:
private static Type GetGenericBaseTypeOfType(Type generic, Type toCheck)
{
while (toCheck != null && toCheck != typeof(object))
{
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (generic == cur)
{
return generic;
}
toCheck = toCheck.BaseType;
}
return null;
}
但是,我无法让PropertyInfo查询其值。
Type genericbaseType = GetGenericBaseTypeOfType(typeof (UpDownBase<>), frameWorkElement.GetType()); // JaredPar StackOverfLow code
{
if (genericbaseType != null)
{
//UpDownBase<int>.ValueProperty ok
// pi3 is null
PropertyInfo pi3 = frameWorkElement.GetType().GetProperty("ValueProperty", BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.Public);
// pi is null
PropertyInfo pi = genericbaseType.GetProperty("ValueProperty", BindingFlags.Static | BindingFlags.Public);
更新2
我接受了Sacrilege解决方案,因为他解决了我最大的问题。我也认为根本不可能做我正在尝试的事情。但是不要试图让它有效,因为它没有。我无法从我使用的GenericType获得的dependencyProperty中获取绑定表达式,而且从我认为的任何泛型中获取,请参阅以下代码和注释:
Type upDownType = typeof(UpDownBase<>).MakeGenericType(frameWorkElement.GetType().BaseType.GenericTypeArguments[0]);
FieldInfo fi = upDownType.GetField("ValueProperty");
if (fi != null)
{
var dp = fi.GetValue(null) as DependencyProperty;
if (dp != null)
{
be = frameWorkElement.GetBindingExpression(dp); // Null
if (be != null)
{
be.UpdateSource();
}
else
{
// Next line be= null
be = frameWorkElement.GetBindingExpression(UpDownBase<int>.ValueProperty); // Null
// Next line be = correct binding expression
be = frameWorkElement.GetBindingExpression(IntegerUpDown.ValueProperty); // Ok valid bindingExpression
}
答案 0 :(得分:2)
您正尝试访问特定实例上的静态属性。你不能用C#做到这一点。
如果您可以对其进行排列,此时T
已知,则您只需拨打UpDownBase<T>.ValueProperty
而不是upDownT.ValueProperty
。否则你将不得不求助于反射来获得T
然后获得财产。
此代码应该可以在不知道T
的情况下获取dp值。
Type upDownType = typeof(UpDownBase<>).MakeGenericType(upDownT.GetType().BaseType.GenericTypeArguments[0]);
DependencyProperty dp = (DependencyProperty)upDownType.GetField("ValueProperty").GetValue(null);
参考更新3
嗯,这使它实际上更容易一些。您应该能够从具体类型中获取depedndecy属性,然后像这样:
DependencyProperty dp = (DependencyProperty)frameWorkElement.GetType().GetField("ValueProperty").GetValue(null);
答案 1 :(得分:0)
以前的答案还可以,但有默认值。返回的对象并不完全是预期的对象(似乎是它的副本)。我认为密钥位于标志中:&#34; FlattenHierarchy&#34;。
以下代码完美运行:
var frameWorkElement = e.OriginalSource as FrameworkElement;
while (frameWorkElement != null)
{
Type genericbaseType = GetGenericBaseTypeOfType(typeof(UpDownBase<>), frameWorkElement.GetType()); // JaredPar StackOverfLow code
{
if (genericbaseType != null)
{
FieldInfo fi = frameWorkElement.GetType().GetField("ValueProperty", BindingFlags.GetField | BindingFlags.Default | BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.SetField);
if (fi != null)
{
var dp = fi.GetValue(null) as DependencyProperty;
if (dp != null)
{
be = frameWorkElement.GetBindingExpression(dp); // Null if done like the other answer.
if (be != null)
{
be.UpdateSource();
}
}
}
break;
}
}
frameWorkElement = VisualTreeHelper.GetParent(frameWorkElement) as FrameworkElement;