From 43e70f1c397024006b5cf39d561503a4fab59769 Mon Sep 17 00:00:00 2001 From: Lamparter <71598437+Lamparter@users.noreply.github.com> Date: Mon, 14 Apr 2025 10:52:44 +0100 Subject: [PATCH 1/4] Create sample pages --- ...on.png => DependencyPropertyGenerator.png} | Bin .../samples/DependencyPropertyGenerator.md | 28 ++++++++++++++++++ ...pendencyPropertyGeneratorCustomSample.xaml | 17 +++++++++++ ...dencyPropertyGeneratorCustomSample.xaml.cs | 16 ++++++++++ 4 files changed, 61 insertions(+) rename components/DependencyPropertyGenerator/samples/Assets/{icon.png => DependencyPropertyGenerator.png} (100%) create mode 100644 components/DependencyPropertyGenerator/samples/DependencyPropertyGenerator.md create mode 100644 components/DependencyPropertyGenerator/samples/DependencyPropertyGeneratorCustomSample.xaml create mode 100644 components/DependencyPropertyGenerator/samples/DependencyPropertyGeneratorCustomSample.xaml.cs diff --git a/components/DependencyPropertyGenerator/samples/Assets/icon.png b/components/DependencyPropertyGenerator/samples/Assets/DependencyPropertyGenerator.png similarity index 100% rename from components/DependencyPropertyGenerator/samples/Assets/icon.png rename to components/DependencyPropertyGenerator/samples/Assets/DependencyPropertyGenerator.png diff --git a/components/DependencyPropertyGenerator/samples/DependencyPropertyGenerator.md b/components/DependencyPropertyGenerator/samples/DependencyPropertyGenerator.md new file mode 100644 index 000000000..7da4b74bc --- /dev/null +++ b/components/DependencyPropertyGenerator/samples/DependencyPropertyGenerator.md @@ -0,0 +1,28 @@ +--- +title: DependencyPropertyGenerator +author: Sergio0694 +description: A source generator for DependencyProperty registration. +keywords: DependencyPropertyGenerator +dev_langs: + - csharp +category: Xaml +subcategory: Developer +experimental: true +discussion-id: 449 +issue-id: 621 +icon: Assets/DependencyPropertyGenerator.png +--- + + + + + + + + + +# DependencyPropertyGenerator + +bla bla bla bla + +> [!Sample DependencyPropertyGeneratorCustomSample] diff --git a/components/DependencyPropertyGenerator/samples/DependencyPropertyGeneratorCustomSample.xaml b/components/DependencyPropertyGenerator/samples/DependencyPropertyGeneratorCustomSample.xaml new file mode 100644 index 000000000..92ba87a9c --- /dev/null +++ b/components/DependencyPropertyGenerator/samples/DependencyPropertyGeneratorCustomSample.xaml @@ -0,0 +1,17 @@ + + + + + + diff --git a/components/DependencyPropertyGenerator/samples/DependencyPropertyGeneratorCustomSample.xaml.cs b/components/DependencyPropertyGenerator/samples/DependencyPropertyGeneratorCustomSample.xaml.cs new file mode 100644 index 000000000..72d6e903d --- /dev/null +++ b/components/DependencyPropertyGenerator/samples/DependencyPropertyGeneratorCustomSample.xaml.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using CommunityToolkit.WinUI; + +namespace DependencyPropertyGenerator.Samples; + +[ToolkitSample(id: nameof(DependencyPropertyGeneratorCustomSample), "Custom control", description: $"A sample for showing how to use {nameof(GeneratedDependencyPropertyAttribute)} to register dependency properties.")] +public sealed partial class DependencyPropertyGeneratorCustomSample : Page +{ + public DependencyPropertyGeneratorCustomSample() + { + this.InitializeComponent(); + } +} From eab0e1c98638f2e9e143c68b3c0478dc78c2605d Mon Sep 17 00:00:00 2001 From: Lamparter <71598437+Lamparter@users.noreply.github.com> Date: Mon, 14 Apr 2025 14:45:28 +0100 Subject: [PATCH 2/4] Add docs --- .../samples/DependencyPropertyGenerator.md | 129 ++++++++++++++++-- 1 file changed, 121 insertions(+), 8 deletions(-) diff --git a/components/DependencyPropertyGenerator/samples/DependencyPropertyGenerator.md b/components/DependencyPropertyGenerator/samples/DependencyPropertyGenerator.md index 7da4b74bc..b8e9fc413 100644 --- a/components/DependencyPropertyGenerator/samples/DependencyPropertyGenerator.md +++ b/components/DependencyPropertyGenerator/samples/DependencyPropertyGenerator.md @@ -13,16 +13,129 @@ issue-id: 621 icon: Assets/DependencyPropertyGenerator.png --- - - - - - +The `DependencyPropertyGenerator` is a source generator that simplifies the registration of `DependencyProperty` fields in your XAML projects. +It automatically generates the boilerplate code needed for property registration, making it easier to work with dependency properties. - +Dependency properties are a key feature in WinUI, allowing for property value inheritance, change notification, and data binding. -# DependencyPropertyGenerator +## Features -bla bla bla bla +- Automatically generates dependency property boilerplate code. +- Supports customization through attributes. +- Ensures consistency and reduces manual errors. +- Improves readability and maintainability of code. + +Like other Windows Community Toolkit components, the DependencyPropertyGenerator supports UWP, Uno Platform and the Windows App SDK. + +## Using `GeneratedDependencyPropertyAttribute` + +To use the `DependencyPropertyGenerator`, you need to add the `GeneratedDependencyPropertyAttribute` to your properties. +This attribute specifies the name of the dependency property and its default value. + +For example, if you were to consume the `DependencyPropertyGenerator` from UWP: + +```cs +namespace MyNamespace; + +public partial class MyControl : DependencyObject +{ + // The GeneratedDependencyPropertyAttribute is used to specify which property to generate the DependencyProperty for. + [GeneratedDependencyProperty(IsLocalCacheEnabled = true)] + // It is required that you mark the property as partial, so that the generator can add additional code to its get() method. + public partial int Number { get; set; } +} +``` + +The source generator would generate *this*: + +```cs +namespace MyNamespace; + +partial class MyControl +{ + /// + /// The backing instance for . + /// + public static readonly DependencyProperty NumberProperty = DependencyProperty.Register( + name: "Number", + propertyType: typeof(int), + ownerType: typeof(MyControl), + typeMetadata: null); + + public partial int Number + { + get => field; + set + { + OnNumberSet(ref value); + + if (EqualityComparer.Default.Equals(field, value)) + { + return; + } + + int __oldValue = field; + + OnNumberChanging(value); + OnNumberChanging(__oldValue, value); + + field = value; + + object? __boxedValue = value; + + OnNumberSet(ref __boxedValue); + + SetValue(NumberProperty, __boxedValue); + + OnNumberChanged(value); + OnNumberChanged(__oldValue, value); + } + } + + /// Executes the logic for when the accessor is invoked + /// The boxed property value that has been produced before assigning to . + /// This method is invoked on the boxed value that is about to be passed to on . + partial void OnNumberSet(ref object propertyValue); + + /// Executes the logic for when the accessor is invoked + /// The property value that is being assigned to . + /// This method is invoked on the raw value being assigned to , before is used. + partial void OnNumberSet(ref int propertyValue); + + /// Executes the logic for when is changing. + /// The new property value being set. + /// This method is invoked right before the value of is changed. + partial void OnNumberChanging(int newValue); + + /// Executes the logic for when is changing. + /// The previous property value that is being replaced. + /// The new property value being set. + /// This method is invoked right before the value of is changed. + partial void OnNumberChanging(int oldValue, int newValue); + + /// Executes the logic for when has just changed. + /// The new property value that has been set. + /// This method is invoked right after the value of is changed. + partial void OnNumberChanged(int newValue); + + /// Executes the logic for when has just changed. + /// The previous property value that has been replaced. + /// The new property value that has been set. + /// This method is invoked right after the value of is changed. + partial void OnNumberChanged(int oldValue, int newValue); + + /// Executes the logic for when has just changed. + /// Event data that is issued by any event that tracks changes to the effective value of this property. + /// This method is invoked by the infrastructure, after the value of is changed. + partial void OnNumberPropertyChanged(DependencyPropertyChangedEventArgs e); + + /// Executes the logic for when any dependency property has just changed. + /// Event data that is issued by any event that tracks changes to the effective value of this property. + /// This method is invoked by the infrastructure, after the value of any dependency property has just changed. + partial void OnPropertyChanged(DependencyPropertyChangedEventArgs e); +} +``` + +> Other DP generators might prefer using an attribute on the class instead, however the Community Toolkit's generator requires you to put the attribute on individual properties. > [!Sample DependencyPropertyGeneratorCustomSample] From 2eb58a4031b98b289cc8f73119e44134089868e2 Mon Sep 17 00:00:00 2001 From: Lamparter <71598437+Lamparter@users.noreply.github.com> Date: Mon, 14 Apr 2025 14:47:28 +0100 Subject: [PATCH 3/4] Remove full generated file in favor of listing methods in DP docs --- .../samples/DependencyPropertyGenerator.md | 52 ++++--------------- 1 file changed, 9 insertions(+), 43 deletions(-) diff --git a/components/DependencyPropertyGenerator/samples/DependencyPropertyGenerator.md b/components/DependencyPropertyGenerator/samples/DependencyPropertyGenerator.md index b8e9fc413..56bee5494 100644 --- a/components/DependencyPropertyGenerator/samples/DependencyPropertyGenerator.md +++ b/components/DependencyPropertyGenerator/samples/DependencyPropertyGenerator.md @@ -46,7 +46,15 @@ public partial class MyControl : DependencyObject } ``` -The source generator would generate *this*: +The source generator would generate the following partial methods: + +- `OnNumberSet`: "Executes the logic for when the `set` accessor `Number` is invoked" +- `OnNumberChanging`: "Executes the logic for when `Number` is changing." +- `OnNumberChanged`: "Executes the logic for when `Number` has just changed." +- `OnNumberPropertyChanged`: "Executes the logic for when `Number` has just changed." +- `OnPropertyChanged`: "Executes the logic for when any dependency property has just changed." + +Alongside the following changes to the `Number` property: ```cs namespace MyNamespace; @@ -91,48 +99,6 @@ partial class MyControl OnNumberChanged(__oldValue, value); } } - - /// Executes the logic for when the accessor is invoked - /// The boxed property value that has been produced before assigning to . - /// This method is invoked on the boxed value that is about to be passed to on . - partial void OnNumberSet(ref object propertyValue); - - /// Executes the logic for when the accessor is invoked - /// The property value that is being assigned to . - /// This method is invoked on the raw value being assigned to , before is used. - partial void OnNumberSet(ref int propertyValue); - - /// Executes the logic for when is changing. - /// The new property value being set. - /// This method is invoked right before the value of is changed. - partial void OnNumberChanging(int newValue); - - /// Executes the logic for when is changing. - /// The previous property value that is being replaced. - /// The new property value being set. - /// This method is invoked right before the value of is changed. - partial void OnNumberChanging(int oldValue, int newValue); - - /// Executes the logic for when has just changed. - /// The new property value that has been set. - /// This method is invoked right after the value of is changed. - partial void OnNumberChanged(int newValue); - - /// Executes the logic for when has just changed. - /// The previous property value that has been replaced. - /// The new property value that has been set. - /// This method is invoked right after the value of is changed. - partial void OnNumberChanged(int oldValue, int newValue); - - /// Executes the logic for when has just changed. - /// Event data that is issued by any event that tracks changes to the effective value of this property. - /// This method is invoked by the infrastructure, after the value of is changed. - partial void OnNumberPropertyChanged(DependencyPropertyChangedEventArgs e); - - /// Executes the logic for when any dependency property has just changed. - /// Event data that is issued by any event that tracks changes to the effective value of this property. - /// This method is invoked by the infrastructure, after the value of any dependency property has just changed. - partial void OnPropertyChanged(DependencyPropertyChangedEventArgs e); } ``` From 7cd14888c3dd2207aff60a7744f97b32e26df401 Mon Sep 17 00:00:00 2001 From: Lamparter <71598437+Lamparter@users.noreply.github.com> Date: Mon, 14 Apr 2025 18:51:33 +0100 Subject: [PATCH 4/4] Rephrase DP generator documentation --- .../samples/DependencyPropertyGenerator.md | 69 ++++++++++--------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/components/DependencyPropertyGenerator/samples/DependencyPropertyGenerator.md b/components/DependencyPropertyGenerator/samples/DependencyPropertyGenerator.md index 56bee5494..1942fdc0d 100644 --- a/components/DependencyPropertyGenerator/samples/DependencyPropertyGenerator.md +++ b/components/DependencyPropertyGenerator/samples/DependencyPropertyGenerator.md @@ -25,13 +25,15 @@ Dependency properties are a key feature in WinUI, allowing for property value in - Ensures consistency and reduces manual errors. - Improves readability and maintainability of code. -Like other Windows Community Toolkit components, the DependencyPropertyGenerator supports UWP, Uno Platform and the Windows App SDK. +Like other Windows Community Toolkit components, the `DependencyPropertyGenerator` supports UWP, Uno Platform and the Windows App SDK. ## Using `GeneratedDependencyPropertyAttribute` To use the `DependencyPropertyGenerator`, you need to add the `GeneratedDependencyPropertyAttribute` to your properties. This attribute specifies the name of the dependency property and its default value. +> Other DP generators might prefer using an attribute on the class instead, however the Community Toolkit's generator requires you to put the attribute on individual properties. + For example, if you were to consume the `DependencyPropertyGenerator` from UWP: ```cs @@ -57,51 +59,52 @@ The source generator would generate the following partial methods: Alongside the following changes to the `Number` property: ```cs -namespace MyNamespace; - -partial class MyControl +public partial int Number { - /// - /// The backing instance for . - /// - public static readonly DependencyProperty NumberProperty = DependencyProperty.Register( - name: "Number", - propertyType: typeof(int), - ownerType: typeof(MyControl), - typeMetadata: null); - - public partial int Number + get => field; + set { - get => field; - set - { - OnNumberSet(ref value); + OnNumberSet(ref value); - if (EqualityComparer.Default.Equals(field, value)) - { - return; - } + if (EqualityComparer.Default.Equals(field, value)) + { + return; + } - int __oldValue = field; + int __oldValue = field; - OnNumberChanging(value); - OnNumberChanging(__oldValue, value); + OnNumberChanging(value); + OnNumberChanging(__oldValue, value); - field = value; + field = value; - object? __boxedValue = value; + object? __boxedValue = value; - OnNumberSet(ref __boxedValue); + OnNumberSet(ref __boxedValue); - SetValue(NumberProperty, __boxedValue); + SetValue(NumberProperty, __boxedValue); - OnNumberChanged(value); - OnNumberChanged(__oldValue, value); - } + OnNumberChanged(value); + OnNumberChanged(__oldValue, value); } } ``` -> Other DP generators might prefer using an attribute on the class instead, however the Community Toolkit's generator requires you to put the attribute on individual properties. +The `DependencyPropertyGenerator` of course also generates the DP registration code itself, aside from the helpful methods listed above. + +For the `Number` property mentioned earlier, the generator would create a static field called `NumberProperty`: + +```cs +/// +/// The backing instance for . +/// +public static readonly DependencyProperty NumberProperty = DependencyProperty.Register( + name: "Number", + propertyType: typeof(int), + ownerType: typeof(MyControl), + typeMetadata: null); +``` + + > [!Sample DependencyPropertyGeneratorCustomSample]