dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.28k stars 1.76k forks source link

[XamlC] Compile x:Reference #20726

Open simonrozsival opened 9 months ago

simonrozsival commented 9 months ago

The x:Reference markup extension is used to point to another element in the XAML tree which has a corresponding x:Name. To lookup an reference, we use ReferenceExtension which looks up the referenced object in the available namescopes.

When the XAML is compiled, we should be able to reference the local variable corresponding to the XAML element with x:Name directly.

Example

XAML

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyMauiApp.MainPage">
    <Label Text="Foo" x:Name="foo" />
    <Label Text="{Binding Text, Source={x:Reference foo}}" />
</ContentPage>

Generated code (decompiled)

 [XamlFilePath("MainPage.xaml")]
 public class MainPage : ContentPage
 {
     [GeneratedCode("Microsoft.Maui.Controls.SourceGen", "1.0.0.0")]
     private Label foo;

     public MainPage()
     {
         InitializeComponent();
     }

     [GeneratedCode("Microsoft.Maui.Controls.SourceGen", "1.0.0.0")]
     [MemberNotNull("foo")]
     private void InitializeComponent()
     {
         Label label = new Label();
-        ReferenceExtension referenceExtension = new ReferenceExtension();
         BindingExtension bindingExtension = new BindingExtension();
         Label label2 = new Label();
         MainPage mainPage;
         NameScope nameScope = (NameScope)(NameScope.GetNameScope(mainPage = this) ?? new NameScope());
         NameScope.SetNameScope(mainPage, nameScope);
         ((INameScope)nameScope).RegisterName("foo", (object)label);
         if (label.StyleId == null)
         {
             label.StyleId = "foo";
         }
         foo = label;
         label.SetValue(Label.TextProperty, "Foo");
         mainPage.SetValue(ContentPage.ContentProperty, label);
-        referenceExtension.Name = "foo";
-        XamlServiceProvider xamlServiceProvider = new XamlServiceProvider();
-        Type typeFromHandle = typeof(IProvideValueTarget);
-        object[] array = new object[0 + 3];
-        array[0] = bindingExtension;
-        array[1] = label2;
-        array[2] = mainPage;
-        object obj;
-        xamlServiceProvider.Add(typeFromHandle, obj = new SimpleValueTargetProvider(array, typeof(BindingExtension).GetRuntimeProperty("Source"), new NameScope[4] { nameScope, nameScope, nameScope, nameScope }, false));
-        xamlServiceProvider.Add(typeof(IReferenceProvider), obj);
-        object source = ((IMarkupExtension)referenceExtension).ProvideValue((IServiceProvider)xamlServiceProvider);
-        bindingExtension.Source = source;
+        bindingExtension.Source = foo;
         bindingExtension.Path = "Text";
         BindingBase binding = ((IMarkupExtension<BindingBase>)bindingExtension).ProvideValue((IServiceProvider)null);
         label2.SetBinding(Label.TextProperty, binding);
         mainPage.SetValue(ContentPage.ContentProperty, label2);
     }
 }

Motivation

simonrozsival commented 9 months ago

/cc @StephaneDelcroix

ghost commented 9 months ago

We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process.