-
Notifications
You must be signed in to change notification settings - Fork 814
specs/XamlBindingHelper_Spec.md #11022
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
rashmi-thakurr
wants to merge
3
commits into
main
Choose a base branch
from
user/rashmithakur/xamlbindinghelper-spec
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+377
−0
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| Setter.ValueProperty | ||
| === | ||
|
|
||
| # Background | ||
|
|
||
| [`Setter`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.setter) | ||
| is a WinUI 3 class that associates a dependency property with a value inside a `Style`. The | ||
| `Setter.Value` property holds the value that will be applied, but until now there has been no | ||
| public `DependencyProperty` identifier exposed for it. | ||
|
|
||
| All `XamlBindingHelper.SetPropertyFrom*` methods require a `DependencyProperty` as their second | ||
| argument (`propertyToSet`). Without a public `DependencyProperty` handle for `Setter.Value`, | ||
| callers cannot use `XamlBindingHelper` to set `Setter.Value` directly — they are forced to box the | ||
| value to `Object` first: | ||
|
|
||
| ```cpp | ||
| // WinUI 3 — current approach (boxing required) | ||
| auto widthSetter = Setter(); | ||
| widthSetter.Value(box_value(300)); | ||
| ``` | ||
|
|
||
| This spec adds a new static property, `Setter.ValueProperty`, that returns the | ||
| `DependencyProperty` identifier for `Setter.Value`. This unlocks `XamlBindingHelper` usage for | ||
| `Setter.Value`, allowing developers to set values without boxing: | ||
|
|
||
| ```cpp | ||
| // WinUI 3 — new approach (no boxing) | ||
| XamlBindingHelper::SetPropertyFromInt32( | ||
| widthSetter, | ||
| Setter::ValueProperty(), | ||
| 300); | ||
| ``` | ||
|
|
||
| ## Goals | ||
|
|
||
| * Expose `Setter.ValueProperty` so callers have a `DependencyProperty` handle to pass as | ||
| `propertyToSet` in `XamlBindingHelper.SetPropertyFrom*` methods. | ||
| * Follow the established pattern of other WinUI 3 classes that expose `DependencyProperty` | ||
| identifiers for their properties. | ||
|
|
||
| ## Non-goals | ||
|
|
||
| * Changing the behavior or storage of `Setter.Value` itself. | ||
| * Adding new overloads to `XamlBindingHelper` (covered in a separate spec). | ||
|
|
||
| # Conceptual pages (How To) | ||
|
|
||
| ## Using Setter.ValueProperty with XamlBindingHelper | ||
|
|
||
| Previously there was no public way to obtain a `DependencyProperty` token for `Setter.Value`. With | ||
| `Setter.ValueProperty`, you can now pass it to any existing `XamlBindingHelper.SetPropertyFrom*` | ||
| overload: | ||
|
|
||
| ```cpp | ||
| auto setter = Setter(); | ||
| // Set an Int32 value without boxing | ||
| XamlBindingHelper::SetPropertyFromInt32(setter, Setter::ValueProperty(), 300); | ||
| ``` | ||
|
|
||
| # API Pages | ||
|
|
||
| ## Setter.ValueProperty property | ||
|
|
||
| Gets the `DependencyProperty` identifier for the | ||
| [`Setter.Value`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.setter.value) | ||
| property. | ||
|
|
||
| ```idl | ||
| static Microsoft.UI.Xaml.DependencyProperty ValueProperty{ get; }; | ||
| ``` | ||
|
|
||
| ### Remarks | ||
|
|
||
| * `ValueProperty` is a read-only static property that returns a singleton `DependencyProperty` | ||
| instance. | ||
| * Its primary purpose is to serve as the `propertyToSet` argument when calling | ||
| `XamlBindingHelper.SetPropertyFrom*` methods targeting `Setter.Value`. | ||
|
|
||
| ### Examples | ||
|
|
||
| * C#: | ||
| ```csharp | ||
| var setter = new Setter(); | ||
| // Use any existing SetPropertyFrom* overload with Setter.ValueProperty | ||
| XamlBindingHelper.SetPropertyFromDouble(setter, Setter.ValueProperty, 16.0); | ||
| ``` | ||
|
|
||
| * C++: | ||
| ```cpp | ||
| auto setter = Setter(); | ||
| // Use any existing SetPropertyFrom* overload with Setter::ValueProperty() | ||
| XamlBindingHelper::SetPropertyFromDouble(setter, Setter::ValueProperty(), 16.0); | ||
| ``` | ||
|
|
||
| # API Details | ||
|
|
||
| ```idl | ||
| namespace Microsoft.UI.Xaml | ||
| { | ||
| [contract(Microsoft.UI.Xaml.WinUIContract, 1)] | ||
| [webhosthidden] | ||
| runtimeclass Setter : Microsoft.UI.Xaml.SetterBase | ||
| { | ||
| // Existing members omitted for brevity | ||
|
|
||
| [contract(Microsoft.UI.Xaml.WinUIContract, 10)] | ||
| [static_name("Microsoft.UI.Xaml.ISetterStatics2")] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ISetterStatics ? |
||
| { | ||
| static Microsoft.UI.Xaml.DependencyProperty ValueProperty{ get; }; | ||
| } | ||
| }; | ||
| } | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,264 @@ | ||
| XamlBindingHelper | ||
| === | ||
|
|
||
| # Background | ||
|
|
||
| [`XamlBindingHelper`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.markup.xamlbindinghelper) | ||
| is a utility class in WinUI 3 that provides static helper methods for setting dependency property | ||
| values without boxing them to `IInspectable`. It already has overloads for primitive types such as | ||
| `Int32`, `Double`, `Boolean`, `String`, and several `Windows.Foundation` structs (`Point`, `Rect`, | ||
| `Size`, `TimeSpan`). | ||
|
|
||
| In WinUI 2, developers could use the | ||
| [`XamlDirect`](https://learn.microsoft.com/uwp/api/windows.ui.xaml.core.direct.xamldirect) API to | ||
| set struct-typed property values directly without boxing. For example `SetThicknessProperty`, | ||
| `SetCornerRadiusProperty`, and `SetColorProperty`. `XamlDirect` was intentionally not carried | ||
| forward to WinUI 3 because it is a narrow, low-level API with a limited number of consumers and | ||
| significant maintenance costs. | ||
|
|
||
| However, there is a real performance gap: developers who need to configure `Setter.Value` with | ||
| struct types - `Thickness`, `CornerRadius`, and `Windows.UI.Color` � currently have no option | ||
| other than boxing the value to `Object` first: | ||
|
|
||
| ```cpp | ||
| // WinUI 3 � current approach (boxing required) | ||
| auto widthSetter = Setter(); | ||
| widthSetter.Value(box_value(300)); | ||
| ``` | ||
|
|
||
| This spec extends `XamlBindingHelper` with three new struct-typed overloads to close that gap: | ||
|
|
||
| - `SetPropertyFromThickness` | ||
| - `SetPropertyFromCornerRadius` | ||
| - `SetPropertyFromColor` | ||
|
|
||
| With these additions, developers can set struct-typed values on a `Setter` without any boxing: | ||
|
|
||
| ```cpp | ||
| // WinUI 3 � new approach (no boxing) | ||
| XamlBindingHelper::SetPropertyFromThickness( | ||
| widthSetter, | ||
| Setter::ValueProperty(), | ||
| thickness); | ||
| ``` | ||
|
|
||
| ## Goals | ||
|
|
||
| * Provide boxing-free helpers for the three most commonly needed struct types when configuring `Setter.Value`. | ||
| * Follow the established `SetPropertyFrom*` naming pattern already present on `XamlBindingHelper`. | ||
|
|
||
| ## Non-goals | ||
|
|
||
| * Re-introducing `XamlDirect` or any part of its API surface into WinUI 3. | ||
| * Adding `SetPropertyFrom*` overloads for every possible WinUI or Windows struct type. | ||
|
|
||
| # Conceptual pages (How To) | ||
|
|
||
| ## Setting Setter.Value without boxing | ||
|
|
||
| Before these APIs, setting a struct-typed value on `Setter.Value` required boxing the value to | ||
| `Object` first. For example, setting a `Thickness` on a `Setter` looked like this: | ||
|
|
||
| ```cpp | ||
| auto setter = Setter(); | ||
| setter.Value(box_value(Thickness{ 2, 4, 2, 4 })); | ||
| ``` | ||
|
|
||
| With the new APIs, the struct can be passed directly and no boxing is needed in application code: | ||
|
|
||
| ```cpp | ||
| auto setter = Setter(); | ||
| Thickness thickness{ 2, 4, 2, 4 }; | ||
| XamlBindingHelper::SetPropertyFromThickness(setter, Setter::ValueProperty(), thickness); | ||
| ``` | ||
|
|
||
| # API Pages | ||
|
|
||
| _(Each level-two section below maps to a docs.microsoft.com API page.)_ | ||
|
|
||
| ## XamlBindingHelper.SetPropertyFromThickness method | ||
|
|
||
| Sets a `Microsoft.UI.Xaml.Thickness` value on the specified dependency property of an object, | ||
| without requiring the caller to box the struct to `IInspectable`. | ||
|
|
||
| ```idl | ||
| static void SetPropertyFromThickness( | ||
| Object dependencyObject, | ||
| Microsoft.UI.Xaml.DependencyProperty propertyToSet, | ||
| Microsoft.UI.Xaml.Thickness value); | ||
| ``` | ||
|
|
||
| ### Parameters | ||
|
|
||
| | Parameter | Type | Description | | ||
| |---|---|---| | ||
| | `dependencyObject` | `object` | The target object that owns `propertyToSet`. | | ||
| | `propertyToSet` | `DependencyProperty` | The dependency property to assign the value to. | | ||
| | `value` | `Microsoft.UI.Xaml.Thickness` | The `Thickness` value to set. | | ||
|
|
||
| ### Examples | ||
|
|
||
| * C#: | ||
| ```csharp | ||
| var thicknessSetter = new Setter(); | ||
| var thickness = new Thickness(); | ||
| thickness.Left = 2; | ||
| thickness.Top = 4; | ||
| thickness.Right = 2; | ||
| thickness.Bottom = 4; | ||
| XamlBindingHelper.SetPropertyFromThickness(thicknessSetter, Setter.ValueProperty, thickness); | ||
| DemoBorder.SetValue(Border.BorderThicknessProperty, thicknessSetter.Value); | ||
| ``` | ||
|
|
||
| * C++: | ||
| ```cpp | ||
| auto thicknessSetter = Setter(); | ||
| Thickness thickness{}; | ||
| thickness.Left = 2; | ||
| thickness.Top = 4; | ||
| thickness.Right = 2; | ||
| thickness.Bottom = 4; | ||
| XamlBindingHelper::SetPropertyFromThickness(thicknessSetter, Setter::ValueProperty(), thickness); | ||
| DemoBorder().SetValue(Border::BorderThicknessProperty(), thicknessSetter.Value()); | ||
| ``` | ||
|
|
||
| ### Remarks | ||
|
|
||
| * If `dependencyObject` or `propertyToSet` is `null`, an exception is thrown by the WinRT layer from the underlying `E_POINTER` failure. | ||
|
|
||
| Sets a `Microsoft.UI.Xaml.CornerRadius` value on the specified dependency property of an object, | ||
| without requiring the caller to box the struct to `IInspectable`. | ||
|
|
||
| ```idl | ||
| static void SetPropertyFromCornerRadius( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here it should be SetPropertyFromThickness right? Also I dont see a section for SetPropertyFromCornerRadius |
||
| Object dependencyObject, | ||
| Microsoft.UI.Xaml.DependencyProperty propertyToSet, | ||
| Microsoft.UI.Xaml.CornerRadius value); | ||
| ``` | ||
|
|
||
| ### Parameters | ||
|
|
||
| | Parameter | Type | Description | | ||
| |---|---|---| | ||
| | `dependencyObject` | `object` | The target object that owns `propertyToSet`. | | ||
| | `propertyToSet` | `DependencyProperty` | The dependency property to assign the value to. | | ||
| | `value` | `Microsoft.UI.Xaml.CornerRadius` | The `CornerRadius` value to set. | | ||
|
|
||
| ### Examples | ||
|
|
||
| * C#: | ||
| ```csharp | ||
| var cornerRadiusSetter = new Setter(); | ||
| var cornerRadius = new CornerRadius(); | ||
| cornerRadius.TopLeft = 5; | ||
| cornerRadius.TopRight = 10; | ||
| cornerRadius.BottomRight = 15; | ||
| cornerRadius.BottomLeft = 20; | ||
| XamlBindingHelper.SetPropertyFromCornerRadius(cornerRadiusSetter, Setter.ValueProperty, cornerRadius); | ||
| DemoBorder.SetValue(Border.CornerRadiusProperty, cornerRadiusSetter.Value); | ||
| ``` | ||
|
|
||
| * C++: | ||
| ```cpp | ||
| auto cornerRadiusSetter = Setter(); | ||
| CornerRadius cornerRadius{}; | ||
| cornerRadius.TopLeft = 5; | ||
| cornerRadius.TopRight = 10; | ||
| cornerRadius.BottomRight = 15; | ||
| cornerRadius.BottomLeft = 20; | ||
| XamlBindingHelper::SetPropertyFromCornerRadius(cornerRadiusSetter, Setter::ValueProperty(), cornerRadius); | ||
| DemoBorder().SetValue(Border::CornerRadiusProperty(), cornerRadiusSetter.Value()); | ||
| ``` | ||
|
|
||
| ### Remarks | ||
|
|
||
| * If `dependencyObject` or `propertyToSet` is `null`, an exception is thrown by the WinRT layer from the underlying `E_POINTER` failure. | ||
|
|
||
| ## XamlBindingHelper.SetPropertyFromColor method | ||
|
|
||
| Sets a `Windows.UI.Color` value on the specified dependency property of an object, without | ||
| requiring the caller to box the struct to `IInspectable`. | ||
|
|
||
| ```idl | ||
| static void SetPropertyFromColor( | ||
| Object dependencyObject, | ||
| Microsoft.UI.Xaml.DependencyProperty propertyToSet, | ||
| Windows.UI.Color value); | ||
| ``` | ||
|
|
||
| ### Parameters | ||
|
|
||
| | Parameter | Type | Description | | ||
| |---|---|---| | ||
| | `dependencyObject` | `object` | The target object that owns `propertyToSet`. | | ||
| | `propertyToSet` | `DependencyProperty` | The dependency property to assign the value to. | | ||
| | `value` | `Windows.UI.Color` | The `Color` value to set. | | ||
|
|
||
| ### Examples | ||
|
|
||
| Setting `Setter.Value` to a color: | ||
|
|
||
| * C#: | ||
| ```csharp | ||
| var colorSetter = new Setter(); | ||
| XamlBindingHelper.SetPropertyFromColor(colorSetter, Setter.ValueProperty, Colors.BlueViolet); | ||
| DemoBorder.SetValue( | ||
| Border.BorderBrushProperty, | ||
| new SolidColorBrush((Windows.UI.Color)colorSetter.Value)); | ||
| ``` | ||
|
|
||
| Setting `SolidColorBrush.ColorProperty` directly on a brush: | ||
|
|
||
| * C#: | ||
| ```csharp | ||
| var brush = new SolidColorBrush(); | ||
| XamlBindingHelper.SetPropertyFromColor(brush, SolidColorBrush.ColorProperty, Colors.BlueViolet); | ||
| DemoBorder.SetValue(Border.BorderBrushProperty, brush); | ||
| ``` | ||
|
|
||
| * C++: | ||
| ```cpp | ||
| auto brush = SolidColorBrush(); | ||
| XamlBindingHelper::SetPropertyFromColor( | ||
| brush, | ||
| SolidColorBrush::ColorProperty(), | ||
| Colors::BlueViolet()); | ||
| DemoBorder().SetValue(Border::BorderBrushProperty(), brush); | ||
| ``` | ||
|
|
||
| ### Remarks | ||
|
|
||
| * If `dependencyObject` or `propertyToSet` is `null`, an exception is thrown by the WinRT layer from the underlying `E_POINTER` failure. | ||
|
|
||
| # API Details | ||
|
|
||
| ```idl | ||
| namespace Microsoft.UI.Xaml.Markup | ||
| { | ||
| [contract(Microsoft.UI.Xaml.WinUIContract, 1)] | ||
| [webhosthidden] | ||
| [default_interface] | ||
| runtimeclass XamlBindingHelper | ||
| { | ||
| // Existing members omitted for brevity | ||
|
|
||
| [contract(Microsoft.UI.Xaml.WinUIContract, 10)] | ||
| { | ||
| static void SetPropertyFromThickness( | ||
| Object dependencyObject, | ||
| Microsoft.UI.Xaml.DependencyProperty propertyToSet, | ||
| Microsoft.UI.Xaml.Thickness value); | ||
|
|
||
| static void SetPropertyFromCornerRadius( | ||
| Object dependencyObject, | ||
| Microsoft.UI.Xaml.DependencyProperty propertyToSet, | ||
| Microsoft.UI.Xaml.CornerRadius value); | ||
|
|
||
| static void SetPropertyFromColor( | ||
| Object dependencyObject, | ||
| Microsoft.UI.Xaml.DependencyProperty propertyToSet, | ||
| Windows.UI.Color value); | ||
| } | ||
| }; | ||
| } | ||
| ``` | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May be we should say, boxing would be required to set values to Setter without XamlBindingHelper