Skip to content

Commit 086a99c

Browse files
committed
fix: ElementName binding in non-toplevel ResourceDictionary
1 parent 10528e1 commit 086a99c

9 files changed

+206
-9
lines changed

src/SourceGenerators/Uno.UI.SourceGenerators/BindableTypeProviders/BindableTypeProvidersGenerationTask.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ public void Execute(GeneratorExecutionContext context)
5959

6060
try
6161
{
62-
6362
if (PlatformHelper.IsValidPlatform(context)
6463
&& !DesignTimeHelper.IsDesignTime(context))
6564
{

src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,9 @@ private string InnerGenerateFile()
335335

336336
if (topLevelControl.Type.Name == "ResourceDictionary")
337337
{
338-
BuildResourceDictionaryBackingClass(writer, topLevelControl);
338+
_isTopLevelDictionary = true;
339339

340+
BuildResourceDictionaryBackingClass(writer, topLevelControl);
340341
BuildTopLevelResourceDictionary(writer, topLevelControl);
341342
}
342343
else
@@ -912,7 +913,6 @@ private string GetImplicitChildTypeDisplayString(XamlObjectDefinition topLevelCo
912913
private void BuildTopLevelResourceDictionary(IIndentedStringBuilder writer, XamlObjectDefinition topLevelControl)
913914
{
914915
TryAnnotateWithGeneratorSource(writer);
915-
_isTopLevelDictionary = true;
916916

917917
using (Scope(Path.GetFileNameWithoutExtension(_fileDefinition.FilePath).Replace(".", "_") + "RD"))
918918
{
@@ -2797,9 +2797,11 @@ private void BuildExtendedProperties(IIndentedStringBuilder outerwriter, XamlObj
27972797
}
27982798
else
27992799
{
2800+
var isMemberInsideResourceDictionary = IsMemberInsideResourceDictionary(objectDefinition);
2801+
28002802
if (
28012803
member.Member.Name == "Name"
2802-
&& !IsMemberInsideResourceDictionary(objectDefinition)
2804+
&& !isMemberInsideResourceDictionary.isInside
28032805
)
28042806
{
28052807
writer.AppendLineInvariant($@"nameScope.RegisterName(""{member.Value}"", {closureName});");
@@ -2808,7 +2810,7 @@ private void BuildExtendedProperties(IIndentedStringBuilder outerwriter, XamlObj
28082810
if (
28092811
member.Member.Name == "Name"
28102812
&& !IsAttachedProperty(member)
2811-
&& !IsMemberInsideResourceDictionary(objectDefinition)
2813+
&& !isMemberInsideResourceDictionary.isInside
28122814
)
28132815
{
28142816
nameMember = member;
@@ -2944,9 +2946,10 @@ private void BuildExtendedProperties(IIndentedStringBuilder outerwriter, XamlObj
29442946
}
29452947
}
29462948

2947-
if (!IsMemberInsideResourceDictionary(objectDefinition, maxDepth: null)
2949+
if (!_isTopLevelDictionary
29482950
&& (HasXBindMarkupExtension(objectDefinition) || HasMarkupExtensionNeedingComponent(objectDefinition)))
29492951
{
2952+
writer.AppendLineInvariant($"/* _isTopLevelDictionary:{_isTopLevelDictionary} */");
29502953
writer.AppendLineInvariant($"this._component_{CurrentScope.ComponentCount} = {closureName};");
29512954
CurrentScope.Components.Add(objectDefinition);
29522955
}
@@ -3715,8 +3718,8 @@ private string GetCustomMarkupExtensionValue(XamlMemberDefinition member)
37153718
.Select(n => IsMemberInside(xamlObject, n))
37163719
.FirstOrDefault(n => n.isInside);
37173720

3718-
private bool IsMemberInsideResourceDictionary(XamlObjectDefinition xamlObject, int? maxDepth = 1)
3719-
=> IsMemberInside(xamlObject, "ResourceDictionary", maxDepth: maxDepth).isInside;
3721+
private (bool isInside, XamlObjectDefinition xamlObject) IsMemberInsideResourceDictionary(XamlObjectDefinition xamlObject, int? maxDepth = 1)
3722+
=> IsMemberInside(xamlObject, "ResourceDictionary", maxDepth: maxDepth);
37203723

37213724
private static (bool isInside, XamlObjectDefinition xamlObject) IsMemberInside(XamlObjectDefinition xamlObject, string typeName, int? maxDepth = null)
37223725
{
@@ -5058,7 +5061,7 @@ private IDisposable TryGenerateDeferedLoadStrategy(IIndentedStringBuilder writer
50585061

50595062
BuildComplexPropertyValue(innerWriter, def, closureName + ".", closureName);
50605063

5061-
if (!IsMemberInsideResourceDictionary(definition, maxDepth: null)
5064+
if (!_isTopLevelDictionary
50625065
&& (HasXBindMarkupExtension(definition) || HasMarkupExtensionNeedingComponent(definition)))
50635066
{
50645067
var componentName = $"_component_{ CurrentScope.ComponentCount}";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<Page x:Class="Uno.UI.Tests.Windows_UI_Xaml_Data.BindingTests.Controls.Binding_ElementName_In_Template_ItemsControl"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
4+
xmlns:local="using:Uno.UI.Tests.Windows_UI_Xaml_Data.xBindTests.Controls"
5+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
6+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
7+
mc:Ignorable="d">
8+
9+
<ItemsControl x:Name="PrimaryActionsList" x:FieldModifier="public" Tag="42">
10+
<ItemsControl.Template>
11+
<ControlTemplate TargetType="ItemsControl">
12+
<ItemsPresenter/>
13+
</ControlTemplate>
14+
</ItemsControl.Template>
15+
<ItemsControl.ItemsPanel>
16+
<ItemsPanelTemplate>
17+
<StackPanel/>
18+
</ItemsPanelTemplate>
19+
</ItemsControl.ItemsPanel>
20+
<ItemsControl.ItemTemplate>
21+
<DataTemplate>
22+
<Button x:Name="button" Tag="{Binding Tag, ElementName=PrimaryActionsList}" />
23+
</DataTemplate>
24+
</ItemsControl.ItemTemplate>
25+
</ItemsControl>
26+
</Page>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel;
4+
using System.IO;
5+
using System.Linq;
6+
using System.Runtime.InteropServices.WindowsRuntime;
7+
using Windows.Foundation;
8+
using Windows.Foundation.Collections;
9+
using Windows.UI.Xaml;
10+
using Windows.UI.Xaml.Controls;
11+
using Windows.UI.Xaml.Controls.Primitives;
12+
using Windows.UI.Xaml.Data;
13+
using Windows.UI.Xaml.Input;
14+
using Windows.UI.Xaml.Media;
15+
using Windows.UI.Xaml.Navigation;
16+
17+
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
18+
19+
namespace Uno.UI.Tests.Windows_UI_Xaml_Data.BindingTests.Controls
20+
{
21+
/// <summary>
22+
/// An empty page that can be used on its own or navigated to within a Frame.
23+
/// </summary>
24+
public sealed partial class Binding_ElementName_In_Template_ItemsControl : Page
25+
{
26+
public Binding_ElementName_In_Template_ItemsControl()
27+
{
28+
this.InitializeComponent();
29+
}
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<Page x:Class="Uno.UI.Tests.Windows_UI_Xaml_Data.BindingTests.Controls.Binding_ElementName_In_Template_Resource"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
4+
xmlns:local="using:Uno.UI.Tests.Windows_UI_Xaml_Data.xBindTests.Controls"
5+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
6+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
7+
mc:Ignorable="d">
8+
9+
<Page.Resources>
10+
<DataTemplate x:Key="myTemplate">
11+
<TextBlock x:Name="innerTextBlock" Text="{Binding Tag, ElementName=topLevel}" />
12+
</DataTemplate>
13+
</Page.Resources>
14+
15+
<Grid>
16+
<ContentControl x:Name="topLevel" x:FieldModifier="public" Tag="42" ContentTemplate="{StaticResource myTemplate}" />
17+
</Grid>
18+
</Page>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel;
4+
using System.IO;
5+
using System.Linq;
6+
using System.Runtime.InteropServices.WindowsRuntime;
7+
using Windows.Foundation;
8+
using Windows.Foundation.Collections;
9+
using Windows.UI.Xaml;
10+
using Windows.UI.Xaml.Controls;
11+
using Windows.UI.Xaml.Controls.Primitives;
12+
using Windows.UI.Xaml.Data;
13+
using Windows.UI.Xaml.Input;
14+
using Windows.UI.Xaml.Media;
15+
using Windows.UI.Xaml.Navigation;
16+
17+
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
18+
19+
namespace Uno.UI.Tests.Windows_UI_Xaml_Data.BindingTests.Controls
20+
{
21+
/// <summary>
22+
/// An empty page that can be used on its own or navigated to within a Frame.
23+
/// </summary>
24+
public sealed partial class Binding_ElementName_In_Template_Resource : Page
25+
{
26+
public Binding_ElementName_In_Template_Resource()
27+
{
28+
this.InitializeComponent();
29+
}
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<Page x:Class="Uno.UI.Tests.Windows_UI_Xaml_Data.BindingTests.Controls.Binding_ElementName_In_Template_Resource_In_Dictionary"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
4+
xmlns:local="using:Uno.UI.Tests.Windows_UI_Xaml_Data.xBindTests.Controls"
5+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
6+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
7+
mc:Ignorable="d">
8+
9+
<Page.Resources>
10+
<ResourceDictionary>
11+
<DataTemplate x:Key="myTemplate">
12+
<TextBlock x:Name="innerTextBlock" Text="{Binding Tag, ElementName=topLevel}" />
13+
</DataTemplate>
14+
</ResourceDictionary>
15+
</Page.Resources>
16+
17+
<Grid>
18+
<ContentControl x:Name="topLevel" x:FieldModifier="public" Tag="42" ContentTemplate="{StaticResource myTemplate}" />
19+
</Grid>
20+
</Page>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel;
4+
using System.IO;
5+
using System.Linq;
6+
using System.Runtime.InteropServices.WindowsRuntime;
7+
using Windows.Foundation;
8+
using Windows.Foundation.Collections;
9+
using Windows.UI.Xaml;
10+
using Windows.UI.Xaml.Controls;
11+
using Windows.UI.Xaml.Controls.Primitives;
12+
using Windows.UI.Xaml.Data;
13+
using Windows.UI.Xaml.Input;
14+
using Windows.UI.Xaml.Media;
15+
using Windows.UI.Xaml.Navigation;
16+
17+
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
18+
19+
namespace Uno.UI.Tests.Windows_UI_Xaml_Data.BindingTests.Controls
20+
{
21+
/// <summary>
22+
/// An empty page that can be used on its own or navigated to within a Frame.
23+
/// </summary>
24+
public sealed partial class Binding_ElementName_In_Template_Resource_In_Dictionary : Page
25+
{
26+
public Binding_ElementName_In_Template_Resource_In_Dictionary()
27+
{
28+
this.InitializeComponent();
29+
}
30+
}
31+
}

src/Uno.UI.Tests/Windows_UI_Xaml_Data/BindingTests/Given_Binding.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,43 @@ public void When_ElementName_In_Template()
2222

2323
Assert.AreEqual(SUT.topLevel.Tag, tb.Text);
2424
}
25+
26+
[TestMethod]
27+
public void When_ElementName_In_Template_Resource()
28+
{
29+
var SUT = new Binding_ElementName_In_Template_Resource();
30+
31+
SUT.ForceLoaded();
32+
33+
var tb = SUT.FindName("innerTextBlock") as Windows.UI.Xaml.Controls.TextBlock;
34+
35+
Assert.AreEqual(SUT.topLevel.Tag, tb.Text);
36+
}
37+
38+
[TestMethod]
39+
public void When_ElementName_In_Template_Resource_In_Dictionary()
40+
{
41+
var SUT = new Binding_ElementName_In_Template_Resource_In_Dictionary();
42+
43+
SUT.ForceLoaded();
44+
45+
var tb = SUT.FindName("innerTextBlock") as Windows.UI.Xaml.Controls.TextBlock;
46+
47+
Assert.AreEqual(SUT.topLevel.Tag, tb.Text);
48+
}
49+
50+
[TestMethod]
51+
public void When_ElementName_In_Template_ItemsControl()
52+
{
53+
var SUT = new Binding_ElementName_In_Template_ItemsControl();
54+
55+
SUT.PrimaryActionsList.ItemsSource = new[] { "test" };
56+
57+
SUT.ForceLoaded();
58+
59+
var button = SUT.FindName("button") as Windows.UI.Xaml.Controls.Button;
60+
61+
Assert.AreEqual(SUT.PrimaryActionsList.Tag, button.Tag);
62+
}
2563
}
2664
}

0 commit comments

Comments
 (0)