# Source: https://raw.githubusercontent.com/unoplatform/uno/refs/heads/master/doc/articles/uno-development/Internal-DependencyProperty-Generator.md

---
uid: Uno.Contributing.DependencyPropertyGenerator
---

# The DependencyProperty Generator

Uno provides an internal `DependencyPproperty` code generator, used to provide the boiler plate for the property, as well as the handling of local-precedence property value caching.

This generator is not available outside of Uno as it is very specific to the needs of the internals of Uno.

The property getters and setters are not generated to avoid VS2019 (as of 16.7 Pre 2) intellisense issues when opening the Uno.UI solution for the first time or after a repository cleanup.

## DependencyProperty declaration

To declare a dependency property, the following code must be provided:

```csharp
[Uno.UI.Xaml.GeneratedDependencyProperty(DefaultValue = "")]
public static readonly DependencyProperty MyStringProperty = CreateMyStringProperty();

public string MyString
{
    get => GetMyStringValue();
    set => SetMyStringValue(value);
}
```

This will automatically generate the `MyStringProperty` member.

## DependencyProperty property changed

```csharp
[Uno.UI.Xaml.GeneratedDependencyProperty(DefaultValue = "")]
public static readonly DependencyProperty MyStringProperty = CreateMyStringProperty();

public string MyString
{
    get => GetMyStringValue();
    set => SetMyStringValue(value);
}

private void OnMyStringChanged(string oldValue, string newValue) 
{
}
```

Declaring an `OnMyStringChanged` will automatically include that method for the property changed. To ensure that the method is defined and used, set the `PropertyChangedCallback` attribute parameter.

The following callback signature is also supported:

```csharp
private void OnMyStringChanged(DependencyPropertyChangedEventArgs args) 
{
}
```

## Attached DependencyProperties generation

Attached dependency properties need to be declared this way, with the `GeneratedDependencyProperty` located on the `GetXXX` method:

```csharp
[GeneratedDependencyProperty(DefaultValue = 0.0d, AttachedBackingFieldOwner = typeof(UIElement), Attached = true)]
public static readonly DependencyProperty LeftProperty = CreateLeftProperty();

public static double GetLeft(DependencyObject obj)
    => GetLeftValue(obj);

public static void SetLeft(DependencyObject obj, double value)
    => SetLeftValue(obj, value);
```

This dependency property will be declared as `LeftProperty`, with the local-precedence cache backing field included in the `UIElement` class.

## DependencyProperty local precedence caching

This feature is about storing the current value that can be read through the C# property getter, or the `GetXXX` method of an attached property. The objective of this feature is to avoid spending time in the dependency property system to read the value, and avoid the type cast required when getting a `DependencyProperty` value.

Backing fields are automatically generated and maintained current through `FrameworkPropertyMetadata.BackingFieldUpdateCallback` which is invoked when the highest precedence value of a `DependencyProperty` is changed.

## GeneratedDependencyProperty options

Other attribute properties are available on `GeneratedDependencyProperty` to include:

- `PropertyChangedCallback` to force the inclusion of a property changed callback method and fail the build if there is none
- `CoerceCallback` to force the inclusion of a coerce callback method and fail the build if there is none
- `Options` to specify which `FrameworkPropertyMetadataOptions` to use
- `LocalCache` to enable or disable local precedence value caching (enabled by default)
- `AttachedBackingFieldOwner` to provide the type hosting the local cache backing field for attached properties
- `ChangedCallbackName` to control the name of the property changed callback method

## Benchmarks

### WebAssembly, using the interpreter (Uno.Wasm.Bootstrap 1.3.0-dev.42)

Before DP caching:

```console
SimpleDPBenchmark.DP_Write: InProcess(Toolchain=InProcessToolchain, IterationCount=5, LaunchCount=1, WarmupCount=1)
Runtime = ; GC = 
Mean = 885.7123 us, StdErr = 12.2709 us (1.39%); N = 5, StdDev = 27.4385 us
Min = 850.0629 us, Q1 = 860.1191 us, Median = 886.3569 us, Q3 = 910.9833 us, Max = 921.5082 us
IQR = 50.8643 us, LowerFence = 783.8227 us, UpperFence = 987.2797 us
ConfidenceInterval = [780.0563 us; 991.3684 us] (CI 99.9%), Margin = 105.6560 us (11.93% of Mean)
Skewness = 0, Kurtosis = 1.19, MValue = 2
-------------------- Histogram --------------------
[846.079 us ; 879.367 us) | @@
[879.367 us ; 907.448 us) | @@
[907.448 us ; 935.549 us) | @
---------------------------------------------------

SimpleDPBenchmark.DP_Read: InProcess(Toolchain=InProcessToolchain, IterationCount=5, LaunchCount=1, WarmupCount=1)
Runtime = ; GC = 
Mean = 83.8832 us, StdErr = 0.7938 us (0.95%); N = 5, StdDev = 1.7749 us
Min = 82.4768 us, Q1 = 82.5403 us, Median = 83.0732 us, Q3 = 85.6311 us, Max = 86.6846 us
IQR = 3.0908 us, LowerFence = 77.9041 us, UpperFence = 90.2674 us
ConfidenceInterval = [77.0487 us; 90.7177 us] (CI 99.9%), Margin = 6.8345 us (8.15% of Mean)
Skewness = 0.6, Kurtosis = 1.39, MValue = 2
-------------------- Histogram --------------------
[81.867 us ; 83.683 us) | @@@
[83.683 us ; 85.486 us) | @
[85.486 us ; 87.593 us) | @
---------------------------------------------------
```

After DP caching:

````console
// * Detailed results *
SimpleDPBenchmark.DP_Write: InProcess(Toolchain=InProcessToolchain, IterationCount=5, LaunchCount=1, WarmupCount=1)
Runtime = ; GC = 
Mean = 938.0835 us, StdErr = 10.0558 us (1.07%); N = 5, StdDev = 22.4856 us
Min = 910.9253 us, Q1 = 915.3540 us, Median = 940.2124 us, Q3 = 959.7485 us, Max = 961.5698 us
IQR = 44.3945 us, LowerFence = 848.7622 us, UpperFence = 1,026.3403 us
ConfidenceInterval = [851.4996 us; 1,024.6674 us] (CI 99.9%), Margin = 86.5839 us (9.23% of Mean)
Skewness = -0.09, Kurtosis = 0.87, MValue = 2
-------------------- Histogram --------------------
[903.848 us ; 939.385 us) | @@
[939.385 us ; 962.397 us) | @@@
---------------------------------------------------

SimpleDPBenchmark.DP_Read: InProcess(Toolchain=InProcessToolchain, IterationCount=5, LaunchCount=1, WarmupCount=1)
Runtime = ; GC = 
Mean = 10.1375 us, StdErr = 0.1325 us (1.31%); N = 5, StdDev = 0.2964 us
Min = 9.6547 us, Q1 = 9.8525 us, Median = 10.2910 us, Q3 = 10.3457 us, Max = 10.3603 us
IQR = 0.4931 us, LowerFence = 9.1128 us, UpperFence = 11.0854 us
ConfidenceInterval = [8.9962 us; 11.2788 us] (CI 99.9%), Margin = 1.1413 us (11.26% of Mean)
Skewness = -0.7, Kurtosis = 1.52, MValue = 2
-------------------- Histogram --------------------
[ 9.503 us ;  9.806 us) | @
[ 9.806 us ; 10.174 us) | @
[10.174 us ; 10.512 us) | @@@
---------------------------------------------------
```