DependencyPropertyGenerator

repository·main·Indexed 41 days ago

https://github.com/havendv/dependencypropertygenerator

A source generator for WPF, UWP, WinUI, Uno, Avalonia, and MAUI that automates boilerplate code for Dependency Properties, Attached Properties, and Routed/Weak Events. It provides attributes to automatically generate property fields, wrappers, and change notification hooks, including support for complex default value expressions and event binding.

Tokens
1.3K
Snippets
4
Records
8
Agent score
50%

What's inside DependencyPropertyGenerator

  1. Use complex expressions in DefaultValue

    main

    While standard C# properties usually avoid new expressions in defaults, this generator allows them via the DefaultValueExpression property. This is useful for initializing properties with new objects or structs.

    If the type is in a different namespace than the attribute, you must provide the fully qualified name.

    public readonly record struct Data();
    
    [AttachedDependencyProperty<object, TreeView>("SelectedItem", DefaultValueExpression = "new Data()",
    // Note: Use full namespace if Data is not in the same namespace as the attribute
    // DefaultValueExpression = "MyNamespace.Data()")]
  2. Define a Dependency Property

    main

    Use the [DependencyProperty] attribute on a partial class to automatically generate the DependencyProperty field, the property wrapper (getter/setter), and change notification hooks. You can specify the property name, DefaultValue, Category, and Description within the attribute.

    To handle property changes, implement the partial void On[PropertyName]Changed(oldValue, newValue) method in your class.

    [DependencyProperty<bool>("IsSpinning", DefaultValue = true, Category = "Category", Description = "Description")]
    public partial class MyControl : UserControl
    {
        // Optional: Handle changes
        partial void OnIsSpinningChanged(bool oldValue, bool newValue)
        {
        }
    }
  3. Configure platform detection for Uno/Avalonia

    main

    If automatic platform detection fails, you can manually define constants in your .csproj file to help the generator identify the target platform:

    <PropertyGroup>
      <DefineConstants>$(DefineConstants);HAS_UNO</DefineConstants>
      <DefineConstants>$(DefineConstants);HAS_UNO_WINUI</DefineConstants>
      <DefineConstants>$(DefineConstants);HAS_AVALONIA</DefineConstants>
    </PropertyGroup>
  4. Add XML documentation to properties

    main

    There are two ways to add documentation:

    1. Simple: Use the Description parameter in the attribute. This adds a System.ComponentModel.Description attribute and populates the XML documentation.
    2. Advanced: Use XmlDocumentation or PropertyXmlDocumentation attribute properties to provide raw XML text for the DependencyProperty or the property's getter/setter.
  5. Define an Attached Dependency Property

    main

    Use the [AttachedDependencyProperty] attribute on a static partial class to generate attached properties. This includes the DependencyProperty field, Get[PropertyName] and Set[PropertyName] methods, and change notification hooks.

    You can specify the DefaultBindingMode (e.g., DefaultBindingMode.TwoWay) via the attribute.

    To handle changes, implement the static partial void On[PropertyName]Changed(sender, oldValue, newValue) method.

    [AttachedDependencyProperty<object, TreeView>("SelectedItem", DefaultBindingMode = DefaultBindingMode.TwoWay)]
    public static partial class TreeViewExtensions
    {
        // Optional: Handle changes
        static partial void OnSelectedItemChanged(TreeView sender, object? oldValue, object? newValue)
        {
        }
    }
  6. Bind a property to an event using BindEvent

    main

    The generator can automatically manage event subscriptions (attaching/detaching) for properties that depend on specific events. Use the BindEvent parameter in the attribute and provide the name of the event (e.g., nameof(Grid.MouseWheel)).

    The generator will create OnBindEventPropertyChanged_BeforeBind and OnBindEventPropertyChanged_AfterBind partial methods that you can use to wrap the subscription logic.

    [AttachedDependencyProperty<object, Grid>("BindEventProperty", BindEvent = nameof(Grid.MouseWheel))]
    public static partial class GridExtensions
    {
        // This method is called during the subscription lifecycle
        private static void OnBindEventPropertyChanged_MouseWheel(object? sender, System.Windows.Input.MouseWheelEventArgs args)
        {
        }
    }