Skip to content

Commit

Permalink
fix: Don't generate invalid code when x:Load and StaticResource marku…
Browse files Browse the repository at this point in the history
…p is used
  • Loading branch information
jeromelaban committed Aug 9, 2021
1 parent e0b62e5 commit 70f756b
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5559,43 +5559,52 @@ private IEnumerable<XamlObjectDefinition> EnumerateSubElements(IEnumerable<XamlO
members.Add(GenerateBinding("Visibility", visibilityMember, definition));
}

if ( (!_isTopLevelDictionary || IsMemberInsideFrameworkTemplate(definition).isInside)
var isInsideFrameworkTemplate = IsMemberInsideFrameworkTemplate(definition).isInside;

if ( (!_isTopLevelDictionary || isInsideFrameworkTemplate)
&& (HasXBindMarkupExtension(definition) || HasMarkupExtensionNeedingComponent(definition)))
{
var componentName = $"_component_{ CurrentScope.ComponentCount}";
writer.AppendLineInvariant($"this.{componentName} = {closureName};");

writer.AppendLineInvariant($"var {componentName}_update_That = ({CurrentResourceOwnerName} as global::Uno.UI.DataBinding.IWeakReferenceProvider).WeakReference;");

if (nameMember != null)
if (!isInsideFrameworkTemplate)
{
writer.AppendLineInvariant($"var {componentName}_update_subject_capture = _{nameMember.Value}Subject;");
}
writer.AppendLineInvariant($"var {componentName}_update_That = ({CurrentResourceOwnerName} as global::Uno.UI.DataBinding.IWeakReferenceProvider).WeakReference;");

using (writer.BlockInvariant($"void {componentName}_update(global::Windows.UI.Xaml.ElementStub sender)"))
{
using (writer.BlockInvariant($"if ({componentName}_update_That.Target is {_className.className} that)"))
if (nameMember != null)
{
writer.AppendLineInvariant($"var {componentName}_update_subject_capture = _{nameMember.Value}Subject;");
}

using (writer.BlockInvariant($"if (sender.IsMaterialized)"))
using (writer.BlockInvariant($"void {componentName}_update(global::Windows.UI.Xaml.ElementStub sender)"))
{
using (writer.BlockInvariant($"if ({componentName}_update_That.Target is {_className.className} that)"))
{
writer.AppendLineInvariant($"that.Bindings.UpdateResources();");

using (writer.BlockInvariant($"if (sender.IsMaterialized)"))
{
writer.AppendLineInvariant($"that.Bindings.UpdateResources();");
}
}
}
}

writer.AppendLineInvariant($"{closureName}.MaterializationChanged += {componentName}_update;");
writer.AppendLineInvariant($"{closureName}.MaterializationChanged += {componentName}_update;");

using (writer.BlockInvariant($"void {componentName}_unloaded(object sender, RoutedEventArgs e)"))
{
// Refresh the bindings when the ElementStub is unloaded. This assumes that
// ElementStub will be unloaded **after** the stubbed control has been created
// in order for the _component_XXX to be filled, and Bindings.Update() to do its work.
writer.AppendLineInvariant($"({componentName}_update_That.Target as {_className.className})?.Bindings.Update();");
}

using (writer.BlockInvariant($"void {componentName}_unloaded(object sender, RoutedEventArgs e)"))
writer.AppendLineInvariant($"{closureName}.Unloaded += {componentName}_unloaded;");
}
else
{
// Refresh the bindings when the ElementStub is unloaded. This assumes that
// ElementStub will be unloaded **after** the stubbed control has been created
// in order for the _component_XXX to be filled, and Bindings.Update() to do its work.
writer.AppendLineInvariant($"({componentName}_update_That.Target as {_className.className})?.Bindings.Update();");
// TODO for https://github.com/unoplatform/uno/issues/6700
}

writer.AppendLineInvariant($"{closureName}.Unloaded += {componentName}_unloaded;");

var xamlObjectDef = new XamlObjectDefinition(elementStubType, 0, 0, definition);
xamlObjectDef.Members.AddRange(members);
CurrentScope.Components.Add(xamlObjectDef);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<UserControl
x:Class="Uno.UI.Tests.Windows_UI_Xaml.Controls.When_xLoad_DataTemplate_In_ResDict"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Uno.UI.Tests.Windows_UI_Xaml.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary Source="When_xLoad_DataTemplate_In_ResDict_Global.xaml"/>
</UserControl.Resources>

<Grid>
<Grid.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Red"/>
</Grid.Resources>
<ContentControl ContentTemplate="{StaticResource MyContainerTemplate}" />
</Grid>
</UserControl>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
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 User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236

namespace Uno.UI.Tests.Windows_UI_Xaml.Controls
{
public sealed partial class When_xLoad_DataTemplate_In_ResDict : UserControl
{
public When_xLoad_DataTemplate_In_ResDict()
{
this.InitializeComponent();
}

public bool MyVisibility
{
get { return (bool)GetValue(MyVisibilityProperty); }
set { SetValue(MyVisibilityProperty, value); }
}

// Using a DependencyProperty as the backing store for MyVisibility. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyVisibilityProperty =
DependencyProperty.Register("MyVisibility", typeof(bool), typeof(When_xLoad_DataTemplate_In_ResDict), new PropertyMetadata(false));
}

public class When_xLoad_DataTemplate_In_ResDict_Model : System.ComponentModel.INotifyPropertyChanged
{
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

private bool visible;

public bool Visible
{
get { return visible; }
set
{
visible = value;
PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof(Visible)));
}
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:xamarin="http://uno.ui/xamarin"
xmlns:local="using:Uno.UI.Tests.Windows_UI_Xaml.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d xamarin">

<DataTemplate x:Key="MyContainerTemplate" x:DataType="local:When_xLoad_DataTemplate_In_ResDict_Model">
<StackPanel>
<TextBlock x:Name="tb01"
Text="Please fill in the empty form fields."
x:Load="{x:Bind Visible, Mode=OneWay}"
Margin="15"
Foreground="{StaticResource MyBrush}" />
<TextBlock x:Name="tb02"
Text="Please fill in the empty form fields."
Margin="15"
Foreground="{StaticResource MyBrush}" />
</StackPanel>
</DataTemplate>

</ResourceDictionary>
31 changes: 31 additions & 0 deletions src/Uno.UI.Tests/Windows_UI_Xaml/Given_xLoad.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,5 +154,36 @@ public void When_xLoad_xBind()
var borders = SUT.EnumerateAllChildren().OfType<Border>();
Assert.AreEqual(0, borders.Count());
}

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

SUT.ForceLoaded();

var stubs = SUT.EnumerateAllChildren().OfType<ElementStub>();
Assert.AreEqual(1, stubs.Count());

var tb02 = SUT.FindName("tb02") as TextBlock;
Assert.IsNotNull(tb02);

var model = new When_xLoad_DataTemplate_In_ResDict_Model();
SUT.DataContext = model;

stubs = SUT.EnumerateAllChildren().OfType<ElementStub>();
Assert.AreEqual(1, stubs.Count());

model.Visible = true;

stubs = SUT.EnumerateAllChildren().OfType<ElementStub>();
Assert.AreEqual(0, stubs.Count());

Assert.AreEqual("[SolidColorBrush #FFFF0000]", tb02.Foreground?.ToString());

var tb01 = SUT.FindName("tb01") as TextBlock;
// This assertion is incorrect because of https://github.com/unoplatform/uno/issues/6700
Assert.AreEqual("[SolidColorBrush #FF000000]", tb01.Foreground?.ToString());
}
}
}

0 comments on commit 70f756b

Please sign in to comment.