roblocop
roblocop

Reputation: 356

How to check if a dependency object contains a dependency property?

Essentially I want some simple reflection where I have an arbitrary DependencyProperty as a parameter. I'd have a special case (in an if statement, for example) if DependencyProperty is defined by / property of a PlaneProjection. I've done some simple fandangling of GetType() but no luck with the expected getters like MemberType.

public void SomeFunc(DependencyProperty dp)
{
    // if dp is a dependency property of plane projection, do something
    // would maybe look like PlaneProjection.hasProperty(dp)
}

Upvotes: 3

Views: 4290

Answers (4)

Glazius
Glazius

Reputation: 739

Dependency properties have default values and will always appear to be set to something when they're retrieved.

You can check if a dependency property has been set on a dependency object, and if so, how, by retrieving and inspecting its ValueSource with the helper DependencyPropertyHelper class -- consider the following:

public static IsPropertyDefault(this DependencyObject obj, DependencyProperty dp)
{
  return DependencyPropertyHelper.GetValueSource(obj, dp).BaseValueSource 
    == BaseValueSource.Default;
}

public static IsPropertySetLocally(this DependencyObject obj, DependencyProperty dp)
{
  return DependencyPropertyHelper.GetValueSource(obj, dp).BaseValueSource 
    == BaseValueSource.Local;
}

One of these should probably be useful to you; if your dependency property can be set by inheritance and you care about that, you can check !IsPropertyDefault. If you specifically care about whether the property has been explicitly declared directly on the object, you can check IsPropertySetLocally.

Upvotes: 1

Kenan E. K.
Kenan E. K.

Reputation: 14111

Try this code with extension methods:

public static class Helpers
{
    public static DependencyProperty FindDependencyProperty(this DependencyObject target, string propName)
    {
        FieldInfo fInfo = target.GetType().GetField(propName, BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.Public);

        if (fInfo == null) return null;

        return (DependencyProperty)fInfo.GetValue(null);
    }

    public static bool HasDependencyProperty(this DependencyObject target, string propName)
    {
        return FindDependencyProperty(target, propName) != null;
    }

    public static string GetStaticMemberName<TMemb>(Expression<Func<TMemb>> expression)
    {
        var body = expression.Body as MemberExpression;

        if (body == null) throw new ArgumentException("'expression' should be a member expression");

        return body.Member.Name;
    }
}

Usage:

planeProjection1.HasDependecyProperty(
    Helpers.GetStaticMemberName(() => PlaneProjection.CenterOfRotationXProperty));

Upvotes: 2

Sam Harwell
Sam Harwell

Reputation: 99869

This should take care of your needs in SilverLight:

private static readonly Dictionary<DependencyProperty, Type> _ownerCache = new Dictionary<DependencyProperty, Type>();
// normally you'd use a HashSet<DependencyProperty>, but it's not available in SilverLight
private static readonly Dictionary<Type, Dictionary<DependencyProperty, bool>> _excludeCache = new Dictionary<Type, Dictionary<DependencyProperty, bool>>();

public static bool IsOwnedByTypeOrParent(DependencyProperty dp, Type type)
{
    lock (_ownerCache)
    {
        Type owner;
        if (_ownerCache.TryGetValue(dp, out owner))
            return owner.IsAssignableFrom(type);

        Dictionary<DependencyProperty, bool> exclude;
        if (_excludeCache.TryGetValue(type, out exclude))
        {
            if (exclude.ContainsKey(dp))
                return false;
        }

        FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.FlattenHierarchy);
        foreach (FieldInfo field in fields)
        {
            if (typeof(DependencyProperty).IsAssignableFrom(field.FieldType))
            {
                try
                {
                    object value = field.GetValue(null);
                    if (object.ReferenceEquals(dp, value))
                    {
                        _ownerCache[dp] = field.DeclaringType;
                        return true;
                    }
                }
                catch
                {
                }
            }
        }

        if (exclude == null)
        {
            exclude = new Dictionary<DependencyProperty, bool>();
            _excludeCache[type] = exclude;
        }

        exclude.Add(dp, false);

        /* optional if you want to minimize memory overhead. unnecessary unless
         * you are using this on enormous numbers of types/DPs
         */
        foreach (var item in _excludeCache)
        {
            item.Value.Remove(dp);
        }

        return false;
    }
}

Upvotes: 0

Sam Harwell
Sam Harwell

Reputation: 99869

Does this condition catch it?

Edit: Only in WPF - not SilverLight.

dp.OwnerType.IsAssignableFrom(typeof(PlaneProjection))

Upvotes: 1

Related Questions