Система DependencyProperty
действительно полезна несколькими способами, но одна из причин, которая вызывает у меня небольшую проблему на данный момент, связана с свойство DataContext, выполняющее некоторую проверку типов. См. Ниже мой текущий подход, который уже останавливает недопустимые типы, вызывающие странные конфликты магии-sting-namespace-collisions, но на самом деле не будет ошибкой при назначении значения.При использовании DependencyProperty, как я могу рассказать разницу между унаследованным значением и назначенным
Проблема только в том, что я не могу понять, как определить разницу между двумя способами, в результате чего значение может оказаться в свойстве. Может ли кто-нибудь сказать мне, как это сделать?
Текущий подход:
(. Пожалуйста, прости ошибки, это набирается из памяти, поэтому может иметь несколько элементов неправильно, но это дает представление)
Базовый класс
public class MyControlBase : FrameworkElement
{
static MyControlBase()
{
DataContextProperty.OverrideDefaultMetadata(
new FrameworkPropertyMetadata(
DataContextProperty.GetMetadata(typeof(MyControlBase)).DefaultValue,
(s,e) => {},
(s,e) =>
{
var sender = s as MyControlBase;
if (sender == null || e == null || sender.ExpectedType == null)
return e;
var oOut = sender.ExpectedType == typeof(e) ? e : null;
// WANTED:
if (!IsInheritedDPValue(sender, DataContextProperty) && e != null && oOut == null)
throw ArgumentException("Assigned value not of expected type");
return Out;
}
)
);
}
public static readonly DependencyProperty ExpectedTypeProperty =
DependencyProperty.Register(
"ExpectedType",
typeof(Type),
typeof(MyControlBase)
new PropertyMetadata(null)
);
public Type ExpectedType {
get {return GetValue(ExpectedTypeProperty) as Type;}
set {SetValue(ExpectedTypeProperty, value);}
}
}
дочерние классы
public class MyControlT1 {
static MyControlT1()
{
ExpectedTypeProperty.OverrideDefaultMetadata(
new FrameworkPropertyMetadata(
typeof(MyControlT1ViewModel)
)
);
}
}
Если это имеет значение? Если вы хотите убедиться, что ваш DataContext имеет ожидаемый тип, вы должны выбросить исключение, когда это не правильно, независимо от того, было ли оно унаследовано или нет. Вы всегда можете попробовать только ReferenceEquals между текущим значением и значением родителя, если вам действительно нужно знать. – Andrew
Это может быть сделано. Например, могу ли я быть уверенным, что значение будет принудительно доведено до нуля в случае исключения (конечно, я могу попытаться увидеть и проверить). Это основное поведение, с которым я столкнулся - исключение будет заключаться в том, чтобы явно заставить потребителей объекта быть осторожным с тем, что они ему назначают, тогда как я ничего не могу сделать с унаследованным значением, похоже, что это вызовет больше проблемы, которые он предотвратит, чтобы бросать каждый раз, когда унаследованное значение изменяется (хотя, конечно, было бы довольно легко сделать этот вариант тоже). – tobriand