Skip to content

Commit

Permalink
fix: ElementName binding in non-toplevel ResourceDictionary
Browse files Browse the repository at this point in the history
  • Loading branch information
jeromelaban committed Jan 18, 2021
1 parent 10528e1 commit 086a99c
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ public void Execute(GeneratorExecutionContext context)

try
{

if (PlatformHelper.IsValidPlatform(context)
&& !DesignTimeHelper.IsDesignTime(context))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,8 +335,9 @@ private string InnerGenerateFile()

if (topLevelControl.Type.Name == "ResourceDictionary")
{
BuildResourceDictionaryBackingClass(writer, topLevelControl);
_isTopLevelDictionary = true;

BuildResourceDictionaryBackingClass(writer, topLevelControl);
BuildTopLevelResourceDictionary(writer, topLevelControl);
}
else
Expand Down Expand Up @@ -912,7 +913,6 @@ private string GetImplicitChildTypeDisplayString(XamlObjectDefinition topLevelCo
private void BuildTopLevelResourceDictionary(IIndentedStringBuilder writer, XamlObjectDefinition topLevelControl)
{
TryAnnotateWithGeneratorSource(writer);
_isTopLevelDictionary = true;

using (Scope(Path.GetFileNameWithoutExtension(_fileDefinition.FilePath).Replace(".", "_") + "RD"))
{
Expand Down Expand Up @@ -2797,9 +2797,11 @@ private void BuildExtendedProperties(IIndentedStringBuilder outerwriter, XamlObj
}
else
{
var isMemberInsideResourceDictionary = IsMemberInsideResourceDictionary(objectDefinition);

if (
member.Member.Name == "Name"
&& !IsMemberInsideResourceDictionary(objectDefinition)
&& !isMemberInsideResourceDictionary.isInside
)
{
writer.AppendLineInvariant($@"nameScope.RegisterName(""{member.Value}"", {closureName});");
Expand All @@ -2808,7 +2810,7 @@ private void BuildExtendedProperties(IIndentedStringBuilder outerwriter, XamlObj
if (
member.Member.Name == "Name"
&& !IsAttachedProperty(member)
&& !IsMemberInsideResourceDictionary(objectDefinition)
&& !isMemberInsideResourceDictionary.isInside
)
{
nameMember = member;
Expand Down Expand Up @@ -2944,9 +2946,10 @@ private void BuildExtendedProperties(IIndentedStringBuilder outerwriter, XamlObj
}
}

if (!IsMemberInsideResourceDictionary(objectDefinition, maxDepth: null)
if (!_isTopLevelDictionary
&& (HasXBindMarkupExtension(objectDefinition) || HasMarkupExtensionNeedingComponent(objectDefinition)))
{
writer.AppendLineInvariant($"/* _isTopLevelDictionary:{_isTopLevelDictionary} */");
writer.AppendLineInvariant($"this._component_{CurrentScope.ComponentCount} = {closureName};");
CurrentScope.Components.Add(objectDefinition);
}
Expand Down Expand Up @@ -3715,8 +3718,8 @@ private string GetCustomMarkupExtensionValue(XamlMemberDefinition member)
.Select(n => IsMemberInside(xamlObject, n))
.FirstOrDefault(n => n.isInside);

private bool IsMemberInsideResourceDictionary(XamlObjectDefinition xamlObject, int? maxDepth = 1)
=> IsMemberInside(xamlObject, "ResourceDictionary", maxDepth: maxDepth).isInside;
private (bool isInside, XamlObjectDefinition xamlObject) IsMemberInsideResourceDictionary(XamlObjectDefinition xamlObject, int? maxDepth = 1)
=> IsMemberInside(xamlObject, "ResourceDictionary", maxDepth: maxDepth);

private static (bool isInside, XamlObjectDefinition xamlObject) IsMemberInside(XamlObjectDefinition xamlObject, string typeName, int? maxDepth = null)
{
Expand Down Expand Up @@ -5058,7 +5061,7 @@ private IDisposable TryGenerateDeferedLoadStrategy(IIndentedStringBuilder writer
BuildComplexPropertyValue(innerWriter, def, closureName + ".", closureName);
if (!IsMemberInsideResourceDictionary(definition, maxDepth: null)
if (!_isTopLevelDictionary
&& (HasXBindMarkupExtension(definition) || HasMarkupExtensionNeedingComponent(definition)))
{
var componentName = $"_component_{ CurrentScope.ComponentCount}";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Page x:Class="Uno.UI.Tests.Windows_UI_Xaml_Data.BindingTests.Controls.Binding_ElementName_In_Template_ItemsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Uno.UI.Tests.Windows_UI_Xaml_Data.xBindTests.Controls"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<ItemsControl x:Name="PrimaryActionsList" x:FieldModifier="public" Tag="42">
<ItemsControl.Template>
<ControlTemplate TargetType="ItemsControl">
<ItemsPresenter/>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button x:Name="button" Tag="{Binding Tag, ElementName=PrimaryActionsList}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238

namespace Uno.UI.Tests.Windows_UI_Xaml_Data.BindingTests.Controls
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class Binding_ElementName_In_Template_ItemsControl : Page
{
public Binding_ElementName_In_Template_ItemsControl()
{
this.InitializeComponent();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Page x:Class="Uno.UI.Tests.Windows_UI_Xaml_Data.BindingTests.Controls.Binding_ElementName_In_Template_Resource"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Uno.UI.Tests.Windows_UI_Xaml_Data.xBindTests.Controls"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Page.Resources>
<DataTemplate x:Key="myTemplate">
<TextBlock x:Name="innerTextBlock" Text="{Binding Tag, ElementName=topLevel}" />
</DataTemplate>
</Page.Resources>

<Grid>
<ContentControl x:Name="topLevel" x:FieldModifier="public" Tag="42" ContentTemplate="{StaticResource myTemplate}" />
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238

namespace Uno.UI.Tests.Windows_UI_Xaml_Data.BindingTests.Controls
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class Binding_ElementName_In_Template_Resource : Page
{
public Binding_ElementName_In_Template_Resource()
{
this.InitializeComponent();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Page x:Class="Uno.UI.Tests.Windows_UI_Xaml_Data.BindingTests.Controls.Binding_ElementName_In_Template_Resource_In_Dictionary"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Uno.UI.Tests.Windows_UI_Xaml_Data.xBindTests.Controls"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Page.Resources>
<ResourceDictionary>
<DataTemplate x:Key="myTemplate">
<TextBlock x:Name="innerTextBlock" Text="{Binding Tag, ElementName=topLevel}" />
</DataTemplate>
</ResourceDictionary>
</Page.Resources>

<Grid>
<ContentControl x:Name="topLevel" x:FieldModifier="public" Tag="42" ContentTemplate="{StaticResource myTemplate}" />
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238

namespace Uno.UI.Tests.Windows_UI_Xaml_Data.BindingTests.Controls
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class Binding_ElementName_In_Template_Resource_In_Dictionary : Page
{
public Binding_ElementName_In_Template_Resource_In_Dictionary()
{
this.InitializeComponent();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,43 @@ public void When_ElementName_In_Template()

Assert.AreEqual(SUT.topLevel.Tag, tb.Text);
}

[TestMethod]
public void When_ElementName_In_Template_Resource()
{
var SUT = new Binding_ElementName_In_Template_Resource();

SUT.ForceLoaded();

var tb = SUT.FindName("innerTextBlock") as Windows.UI.Xaml.Controls.TextBlock;

Assert.AreEqual(SUT.topLevel.Tag, tb.Text);
}

[TestMethod]
public void When_ElementName_In_Template_Resource_In_Dictionary()
{
var SUT = new Binding_ElementName_In_Template_Resource_In_Dictionary();

SUT.ForceLoaded();

var tb = SUT.FindName("innerTextBlock") as Windows.UI.Xaml.Controls.TextBlock;

Assert.AreEqual(SUT.topLevel.Tag, tb.Text);
}

[TestMethod]
public void When_ElementName_In_Template_ItemsControl()
{
var SUT = new Binding_ElementName_In_Template_ItemsControl();

SUT.PrimaryActionsList.ItemsSource = new[] { "test" };

SUT.ForceLoaded();

var button = SUT.FindName("button") as Windows.UI.Xaml.Controls.Button;

Assert.AreEqual(SUT.PrimaryActionsList.Tag, button.Tag);
}
}
}

0 comments on commit 086a99c

Please sign in to comment.