December 5, 2014

No more DependencyProperty with AutoDependencyProperty.Fody

DependencyProperty declarations in WPF are ridiculously redundant and repetitive. Sure there are code snippets that will generate all the boilerplate, but the generated code is a mess to read. The only way to remove the boilerplate while keeping WPF happy is to generate the code during build and that's what my AutoDependencyProperty.Fody is for.

As the name suggests, AutoDependencyProperty.Fody is a Fody plugin. It runs after build and transforms simple automatic C# properties into WPF-friendly dependency properties. Here's what your code looks like with AutoDependencyProperty.Fody:

[AutoDependencyProperty]
public bool HelloWorld { get; set; }

And this is what it will look like to WPF when the application is run:

public static readonly DependencyProperty HelloWorldProperty
    = DependencyProperty.Register(
    "HelloWorld", typeof(bool), typeof(MyControl));
public bool HelloWorld
{
    get { return (bool)GetValue(HelloWorldProperty); }
    set { SetValue(HelloWorldProperty, value); }
}

Everything should work smoothly. Debugger will step through your code, not the generated code. XAML preview in Visual Studio will recognize the dependency property.

The only issue I have encountered is that TemplateBinding won't compile on generated properties. It's probably syntax-checked before Fody gets the chance to transform the code. You will have to use regular Binding with RelativeSource instead.

You can also apply the property to the class in order to transform all properties in it. You can also specify metadata options like this:

[AutoDependencyProperty(Options
    = FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)]
public bool HelloWorld { get; set; }

In order to enjoy this comfort, get AutoDependencyProperty.Fody from NuGet. It will automatically pull Fody with it, which will setup your project to run AutoDependencyProperty.Fody after build. You can also get sources of AutoDependencyProperty.Fody.

4 comments:

  1. Looks like a great package.
    I get the error below on even the simplest build though, framework 4.0, 4.5, 4.6 :

    Severity Code Description Project File Line
    Error Fody: An unhandled exception occurred:
    Exception:
    FodyDependencyProperty weaver failed to load WindowsBase
    StackTrace:
    at ModuleWeaver.Check[T](Func`1 func, String message)
    at ModuleWeaver.CheckAssembly(String name)
    at ModuleWeaver.Execute()
    at lambda_method(Closure , Object )
    at InnerWeaver.ExecuteWeavers() in c:\ConsoleBuildAgent\work\ed448661dbb30d2e\FodyIsolated\InnerWeaver.cs:line 144
    at InnerWeaver.Execute() in c:\ConsoleBuildAgent\work\ed448661dbb30d2e\FodyIsolated\InnerWeaver.cs:line 62
    Source:
    AutoDependencyProperty.Fody
    TargetSite:
    T Check[T](System.Func`1[T], System.String)
    Sequence contains no elements
    StackTrace:
    at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
    at ModuleWeaver.<>c__DisplayClass30.b__2d()
    at ModuleWeaver.Check[T](Func`1 func, String message)
    Source:
    System.Core
    TargetSite:
    TSource First[TSource](System.Collections.Generic.IEnumerable`1[TSource]) FodyTest

    ReplyDelete
    Replies
    1. This happens if the Project does not directly use any Type in WindowsBase - then the Compiler just removes that reference and 'CheckAssembly' fails because there is no match in `.First()`.

      Delete
  2. Thanks for the report. I cannot work on this right now, but I have enabled Issues section on the BitBucket project and if you submit the bug there, I will get back to it later.

    ReplyDelete
  3. Hi! I just checked AutoDependencyProperty.Signed.Fody 1.2.2.3. There seem to be some minor issues.

    First, the signed package does write the FodyWeavers.xml including '.Signed' but only works without it.

    Second, that version has a 1.2.2.2 in its meta data.

    Just wanted you to know.

    ReplyDelete