diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TDBMIDTIRD/XamlCodeGenerator_MyResourceDictionary_92716e07ff456818f6d4125e055d4d57.cs b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TDBMIDTIRD/XamlCodeGenerator_MyResourceDictionary_92716e07ff456818f6d4125e055d4d57.cs index a6e3e15cbe04..ee3191108d83 100644 --- a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TDBMIDTIRD/XamlCodeGenerator_MyResourceDictionary_92716e07ff456818f6d4125e055d4d57.cs +++ b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TDBMIDTIRD/XamlCodeGenerator_MyResourceDictionary_92716e07ff456818f6d4125e055d4d57.cs @@ -95,6 +95,7 @@ public _View Build(object __ResourceOwner_1) __fe.Loading += delegate { _component_0.UpdateResourceBindings(); + _component_0.ApplyXBind(); } ; } @@ -261,6 +262,7 @@ public _View Build(object __ResourceOwner_1) __fe.Loading += delegate { _component_0.UpdateResourceBindings(); + _component_0.ApplyXBind(); } ; } @@ -350,6 +352,7 @@ public _View Build(object __ResourceOwner_1) __fe.Loading += delegate { _component_0.UpdateResourceBindings(); + _component_0.ApplyXBind(); } ; } diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs index 3ead4da769ea..5f23b7778c7a 100644 --- a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs +++ b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs @@ -1084,6 +1084,7 @@ private void BuildCompiledBindingsInitializerForTemplate(IIndentedStringBuilder using (writer.BlockInvariant($"__fe.Loading += delegate")) { BuildComponentResouceBindingUpdates(writer); + BuildXBindApply(writer); BuildxBindEventHandlerInitializers(writer, CurrentScope.xBindEventsHandlers); } writer.AppendLineIndented(";"); @@ -1117,6 +1118,19 @@ private void BuildComponentResouceBindingUpdates(IIndentedStringBuilder writer) } } + private void BuildXBindApply(IIndentedStringBuilder writer) + { + for (var i = 0; i < CurrentScope.Components.Count; i++) + { + var component = CurrentScope.Components[i]; + + if (HasXBindMarkupExtension(component.XamlObject) && IsDependencyObject(component.XamlObject)) + { + writer.AppendLineIndented($"{component.MemberName}.ApplyXBind();"); + } + } + } + private void BuildComponentFields(IIndentedStringBuilder writer) { for (var i = 0; i < CurrentScope.Components.Count; i++) @@ -4230,8 +4244,10 @@ private string BuildXBindEvalFunction(XamlMemberDefinition member, XamlObjectDef var modeMember = bindNode.Members.FirstOrDefault(m => m.Member.Name == "Mode")?.Value?.ToString() ?? GetDefaultBindMode(); var rawBindBack = bindNode.Members.FirstOrDefault(m => m.Member.Name == "BindBack")?.Value?.ToString(); + var sourceInstance = CurrentResourceOwner is not null ? CurrentResourceOwnerName : "__that"; + var applyBindingParameters = _isHotReloadEnabled - ? "__that, (___b, __that)" + ? $"{sourceInstance}, (___b, {sourceInstance})" : "___b"; if (isInsideDataTemplate) @@ -4396,7 +4412,7 @@ string buildBindBack() ? ", new [] {" + string.Join(", ", formattedPaths) + "}" : ""; - return $".BindingApply({applyBindingParameters} => /*defaultBindMode{GetDefaultBindMode()} {rawFunction}*/ global::Uno.UI.Xaml.BindingHelper.SetBindingXBindProvider(___b, __that, ___ctx => {bindFunction}, {buildBindBack()} {pathsArray}))"; + return $".BindingApply({applyBindingParameters} => /*defaultBindMode{GetDefaultBindMode()} {rawFunction}*/ global::Uno.UI.Xaml.BindingHelper.SetBindingXBindProvider(___b, {sourceInstance}, ___ctx => {bindFunction}, {buildBindBack()} {pathsArray}))"; } } diff --git a/src/Uno.UI.RuntimeTests/Tests/BindingTests/BindingTests.cs b/src/Uno.UI.RuntimeTests/Tests/BindingTests/BindingTests.cs index 77b1a3fc8ba0..766866959400 100644 --- a/src/Uno.UI.RuntimeTests/Tests/BindingTests/BindingTests.cs +++ b/src/Uno.UI.RuntimeTests/Tests/BindingTests/BindingTests.cs @@ -128,4 +128,24 @@ public async Task When_FallbackValueThemeResource_WithDataContext() Assert.AreEqual(Microsoft.UI.Colors.Red, ((SolidColorBrush)myBtn.Foreground).Color); } + + [TestMethod] + public async Task When_XBind_To_Const_Page() + { + var SUT = new XBindConstPage(); + await UITestHelper.Load(SUT); + + Assert.AreEqual(200, SUT.XBoundBorder.ActualWidth); + Assert.AreEqual(200, SUT.XBoundBorder.ActualHeight); + } + + [TestMethod] + public async Task When_XBind_To_Const_Control_Template() + { + var SUT = new XBindConstControl(); + await UITestHelper.Load(SUT); + + Assert.AreEqual(200, SUT.XBoundBorder.ActualWidth); + Assert.AreEqual(200, SUT.XBoundBorder.ActualHeight); + } } diff --git a/src/Uno.UI.RuntimeTests/Tests/BindingTests/XBindConstControl.xaml b/src/Uno.UI.RuntimeTests/Tests/BindingTests/XBindConstControl.xaml new file mode 100644 index 000000000000..676d88c1ab33 --- /dev/null +++ b/src/Uno.UI.RuntimeTests/Tests/BindingTests/XBindConstControl.xaml @@ -0,0 +1,48 @@ +<Control + x:Class="Uno.UI.RuntimeTests.Tests.XBindConstControl" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:local="using:Uno.UI.RuntimeTests.Tests" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + mc:Ignorable="d" + d:DesignHeight="300" + d:DesignWidth="400"> + + <Control.Resources> + <ResourceDictionary> + + <Style TargetType="local:XBindConstControl"> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="local:XBindConstControl" > + <Grid> + <StackPanel + HorizontalAlignment="Center" + VerticalAlignment="Center"> + <TextBlock Text="Grid in Control" HorizontalAlignment="Center" /> + <Border + Width="100" + Height="100" + BorderBrush="Black" + BorderThickness="1" + Background="LightCoral" /> + <TextBlock Text="Grid in Control with x:Bind" HorizontalAlignment="Center" /> + <Border + Width="{x:Bind local:XBindConstControl.MyWidth}" + Height="{x:Bind local:XBindConstControl.MyHeight}" + x:Name="BoundBorder" + BorderBrush="Black" + BorderThickness="1" + Background="LawnGreen" /> + </StackPanel> + </Grid> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + </ResourceDictionary> + </Control.Resources> + +</Control> diff --git a/src/Uno.UI.RuntimeTests/Tests/BindingTests/XBindConstControl.xaml.cs b/src/Uno.UI.RuntimeTests/Tests/BindingTests/XBindConstControl.xaml.cs new file mode 100644 index 000000000000..0ab167c8306b --- /dev/null +++ b/src/Uno.UI.RuntimeTests/Tests/BindingTests/XBindConstControl.xaml.cs @@ -0,0 +1,27 @@ +using Microsoft.UI.Xaml.Controls; + +namespace Uno.UI.RuntimeTests.Tests; + +public sealed partial class XBindConstControl : Control +{ + private const double MyWidth = 200; + private const double MyHeight = 200; + + public XBindConstControl() + { + DefaultStyleKey = typeof(XBindConstControl); + + this.InitializeComponent(); + } + + public Border XBoundBorder { get; set; } + + protected override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + XBoundBorder = GetTemplateChild("BoundBorder") as Border; + + + } +} diff --git a/src/Uno.UI.RuntimeTests/Tests/BindingTests/XBindConstPage.xaml b/src/Uno.UI.RuntimeTests/Tests/BindingTests/XBindConstPage.xaml new file mode 100644 index 000000000000..c87d58e9364c --- /dev/null +++ b/src/Uno.UI.RuntimeTests/Tests/BindingTests/XBindConstPage.xaml @@ -0,0 +1,29 @@ +<Page x:Class="Uno.UI.RuntimeTests.Tests.XBindConstPage" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:local="using:Uno.UI.RuntimeTests.Tests" + Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> + <ScrollViewer> + <Grid> + <StackPanel + HorizontalAlignment="Center" + VerticalAlignment="Center"> + <TextBlock Text="Grid in Page" HorizontalAlignment="Center"/> + <Grid + Width="100" + Height="100" + BorderBrush="Black" + BorderThickness="1" + Background="LightCoral" /> + <TextBlock Text="Grid in Page, with x:Bind" HorizontalAlignment="Center" /> + <Border + Width="{x:Bind local:XBindConstPage.MyWidth}" + Height="{x:Bind local:XBindConstPage.MyHeight}" + x:Name="BoundBorder" + BorderBrush="Black" + BorderThickness="1" + Background="LawnGreen" /> + </StackPanel> + </Grid> + </ScrollViewer> +</Page> diff --git a/src/Uno.UI.RuntimeTests/Tests/BindingTests/XBindConstPage.xaml.cs b/src/Uno.UI.RuntimeTests/Tests/BindingTests/XBindConstPage.xaml.cs new file mode 100644 index 000000000000..107fca0a7e32 --- /dev/null +++ b/src/Uno.UI.RuntimeTests/Tests/BindingTests/XBindConstPage.xaml.cs @@ -0,0 +1,16 @@ +using Microsoft.UI.Xaml.Controls; + +namespace Uno.UI.RuntimeTests.Tests; + +public sealed partial class XBindConstPage : Page +{ + private const double MyWidth = 200; + private const double MyHeight = 200; + + public XBindConstPage() + { + this.InitializeComponent(); + } + + public Border XBoundBorder => BoundBorder; +}