tobriand
tobriand

Reputation: 1167

When using a DependencyProperty, how can I tell the the difference between an inherited value and an assigned one

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

Answers (1)

Domysee
Domysee

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

Related Questions