Reputation: 1167
The DependencyProperty
system is really useful in a number of ways, but one which is causing me a little trouble at the moment is, with the DataContext property, doing some type checking. See below for my current approach, which already stops invalid types from causing weird magic-sting-namespace-collisions, but won't actually error on a value being assigned.
Only problem is I can't work out how to tell the difference between the two ways a value can end up in a property. Can someone tell me how to do this?
Current approach:
(Please forgive errors, this is typed from memory, so might have a couple of elements wrong, but it gives the idea.)
Base Class
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);}
}
}
Child classes
public class MyControlT1 {
static MyControlT1()
{
ExpectedTypeProperty.OverrideDefaultMetadata(
new FrameworkPropertyMetadata(
typeof(MyControlT1ViewModel)
)
);
}
}
Upvotes: 0
Views: 282
Reputation: 12846
If you want to know how the value got assigned to the dependency property, you can use
DependencyPropertyHelper.GetValueSource(DependencyObject dependencyObject, DependencyProperty dependencyProperty)
This method returns a ValueSource
object, which has a BaseValueSource
property. It is an enum that has a value according to the place the value came from (inherited, local value, trigger and so on).
If the value was inherited from a parent object, the value of BaseValueSource
would be Inherited
. If the value was directly assigned to the element, the value would be Local
.
You can look up all possible values of BaseValueSource
here: https://msdn.microsoft.com/en-us/library/system.windows.basevaluesource%28v=vs.110%29.aspx
Upvotes: 2