Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looking for DependencyProperty.Register shortcut

Defining WPF properties is too long:

public static readonly DependencyProperty FooProperty = 
  DependencyProperty.Register("Foo", typeof(string), typeof(FooClass), new PropertyMetadata("Foooooo"));

I have a helper method, making it a bit shorter:

public static readonly DependencyProperty FooProperty =
  WpfUtils.Property<string, FooControl>("Foo", "Foooooo");

Code:

public partial class WpfUtils 
{
    public static DependencyProperty Property<T, TClass>(string name) 
    {
        return Property<T, TClass>(name, default(T));
    }

    public static DependencyProperty Property<T, TClass>(string name, T defaultValue) 
    {
        return DependencyProperty.Register(name, typeof(T), typeof(TClass), new PropertyMetadata(defaultValue));
    }
}

Are there better helpers around?

like image 563
alex2k8 Avatar asked Dec 07 '22 08:12

alex2k8


1 Answers

Here is some code for that. This code is evil, but I wanted to show how to do this without using Cecil, or having to create a sourceforge project :-)

To use it, call:

public static readonly DependencyProperty FooProperty = D.P();

And the code is:

public class D
{
    [MethodImpl(MethodImplOptions.NoInlining)]
    public static DependencyProperty P()
    {
        StackTrace stackTrace = new StackTrace();
        StackFrame oneUp = stackTrace.GetFrame(1);
        MethodBase callingMethod = oneUp.GetMethod();
        if (!(callingMethod is ConstructorInfo))
        {
            throw new InvalidOperationException("This method must be called from a static constructor/initializer");
        }
        byte[] staticConstructorCode = callingMethod.GetMethodBody().GetILAsByteArray();
        int offsetAfterThisCall = oneUp.GetILOffset() + 5;

        while (staticConstructorCode[offsetAfterThisCall] == OpCodes.Nop.Value)
        {
            offsetAfterThisCall++;
        }

        if (staticConstructorCode[offsetAfterThisCall] != OpCodes.Stsfld.Value)
        {
            throw new InvalidOperationException("Unexpected IL");
        }

        int token = BitConverter.ToInt32(staticConstructorCode, offsetAfterThisCall + 1);

        FieldInfo field = callingMethod.Module.ResolveField(token);

        if (!field.Name.EndsWith("Property") || field.FieldType != typeof(DependencyProperty))
        {
            throw new NotSupportedException("The field the return value of this method will be stored in must be named xxxProperty and be of type DependencyProperty");
        }

        string name = field.Name.Substring(0, field.Name.Length - "Property".Length);
        return DependencyProperty.Register(name, callingMethod.DeclaringType.GetProperty(name).PropertyType, callingMethod.DeclaringType);
    }
}
like image 83
Alun Harford Avatar answered Dec 11 '22 08:12

Alun Harford