Skip to content

Commit

Permalink
Merge pull request #8314 from unoplatform/dev/jela/xbind-static-handler
Browse files Browse the repository at this point in the history
  • Loading branch information
jeromelaban authored Mar 13, 2022
2 parents 57062cb + 1e30a7d commit 487cc9e
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -838,7 +838,7 @@ private void BuildBackingFields(IIndentedStringBuilder writer)
}
}

private static readonly char[] ResourceInvalidCharacters = new[] { '.', '-' };
private static readonly char[] ResourceInvalidCharacters = new[] { '.', '-', ':' };

private static string? SanitizeResourceName(string? name)
{
Expand Down Expand Up @@ -3535,6 +3535,17 @@ void writeEvent(string? ownerPrefix)
CurrentScope.XBindExpressions.Add(bind);

var eventTarget = XBindExpressionParser.RestoreSinglePath(bind.Members.First().Value?.ToString());

if(eventTarget == null)
{
throw new InvalidOperationException("x:Bind event path cannot by empty");
}

var parts = eventTarget.Split('.').ToList();
var isStaticTarget = parts.FirstOrDefault()?.Contains(":") ?? false;

eventTarget = RewriteNamespaces(eventTarget);

// x:Bind to second-level method generates invalid code
// sanitizing member.Member.Name so that "ViewModel.SearchBreeds" becomes "ViewModel_SearchBreeds"
var sanitizedEventTarget = SanitizeResourceName(eventTarget);
Expand All @@ -3547,11 +3558,17 @@ IMethodSymbol FindTargetMethodSymbol(INamedTypeSymbol? sourceType)
{
ITypeSymbol? currentType = sourceType;

var parts = eventTarget.Split('.');
if (isStaticTarget)
{
// First part is a type for static method binding and should
// overide the original source type
currentType = GetType(RewriteNamespaces(parts[0]));
parts.RemoveAt(0);
}

for (var i = 0; i < parts.Length - 1; i++)
for (var i = 0; i < parts.Count - 1; i++)
{
var next = currentType.GetAllMembersWithName(parts[i]).FirstOrDefault();
var next = currentType.GetAllMembersWithName(RewriteNamespaces(parts[i])).FirstOrDefault();

currentType = next switch
{
Expand Down Expand Up @@ -3623,7 +3640,16 @@ IMethodSymbol FindTargetMethodSymbol(INamedTypeSymbol? sourceType)
//
writer.AppendLineInvariant($"var {member.Member.Name}_{sanitizedEventTarget}_That = {targetContext.weakReference};");

writer.AppendLineInvariant($"/* first level targetMethod:{targetContext.targetMethod} */ {closureName}.{member.Member.Name} += ({parms}) => ({targetContext.target})?.{eventTarget}({xBindParams});");
writer.AppendLineInvariant($"/* first level targetMethod:{targetContext.targetMethod} */ {closureName}.{member.Member.Name} += ({parms}) => ");

if (isStaticTarget)
{
writer.AppendLineInvariant($"{eventTarget}({xBindParams});");
}
else
{
writer.AppendLineInvariant($"({targetContext.target})?.{eventTarget}({xBindParams});");
}
}

writer.AppendLineInvariant($";");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Page x:Class="Uno.UI.Tests.Windows_UI_Xaml_Data.xBindTests.Controls.Binding_Static_Event"
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">

<Grid>
<CheckBox x:Name="myCheckBox"
x:FieldModifier="public"
Checked="{x:Bind local:Binding_Static_Event_Class.OnCheckedRaised}"
Unchecked="{x:Bind local:Binding_Static_Event_Class.OnUncheckedRaised}"/>
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
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.xBindTests.Controls
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class Binding_Static_Event : Page
{
public Binding_Static_Event()
{
this.InitializeComponent();
}

}

public static class Binding_Static_Event_Class
{

public static int CheckedRaised { get; private set; }
public static int UncheckedRaised { get; private set; }

public static void OnCheckedRaised()
{
CheckedRaised++;
}

public static void OnUncheckedRaised(object sender, RoutedEventArgs args)
{
UncheckedRaised++;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Page x:Class="Uno.UI.Tests.Windows_UI_Xaml_Data.xBindTests.Controls.Binding_Static_Event_DataTemplate"
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">

<ContentControl x:Name="root"
x:FieldModifier="public">
<ContentControl.ContentTemplate>
<DataTemplate x:DataType="local:Binding_Static_Event_DataTemplate_Model">
<Grid>
<CheckBox x:Name="myCheckBox"
x:FieldModifier="public"
Checked="{x:Bind local:Binding_Static_Event_DataTemplate_Model_Class.OnCheckedRaised}"
Unchecked="{x:Bind local:Binding_Static_Event_DataTemplate_Model_Class.OnUncheckedRaised}"/>
</Grid>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
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.xBindTests.Controls
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class Binding_Static_Event_DataTemplate : Page
{
public Binding_Static_Event_DataTemplate()
{
this.InitializeComponent();
}

}

public class Binding_Static_Event_DataTemplate_Model { }

public static class Binding_Static_Event_DataTemplate_Model_Class
{
public static int CheckedRaised { get; private set; }
public static int UncheckedRaised { get; private set; }

internal static void OnCheckedRaised()
{
CheckedRaised++;
}

internal static void OnUncheckedRaised(object sender, RoutedEventArgs args)
{
UncheckedRaised++;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,29 @@ public void When_Event()
Assert.AreEqual(1, SUT.UncheckedRaised);
}

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

SUT.ForceLoaded();

var checkBox = SUT.FindName("myCheckBox") as CheckBox;

Assert.AreEqual(0, Binding_Static_Event_Class.CheckedRaised);
Assert.AreEqual(0, Binding_Static_Event_Class.UncheckedRaised);

checkBox.IsChecked = true;

Assert.AreEqual(1, Binding_Static_Event_Class.CheckedRaised);
Assert.AreEqual(0, Binding_Static_Event_Class.UncheckedRaised);

checkBox.IsChecked = false;

Assert.AreEqual(1, Binding_Static_Event_Class.CheckedRaised);
Assert.AreEqual(1, Binding_Static_Event_Class.UncheckedRaised);
}

[TestMethod]
public void When_Event_Nested()
{
Expand Down Expand Up @@ -786,6 +809,33 @@ public void When_Event_DataTemplate()
Assert.AreEqual(1, dc.UncheckedRaised);
}


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

SUT.ForceLoaded();

var root = SUT.FindName("root") as FrameworkElement;
root.DataContext = new object();

var checkBox = SUT.FindName("myCheckBox") as CheckBox;

Assert.AreEqual(0, Binding_Static_Event_DataTemplate_Model_Class.CheckedRaised);
Assert.AreEqual(0, Binding_Static_Event_DataTemplate_Model_Class.UncheckedRaised);

checkBox.IsChecked = true;

Assert.AreEqual(1, Binding_Static_Event_DataTemplate_Model_Class.CheckedRaised);
Assert.AreEqual(0, Binding_Static_Event_DataTemplate_Model_Class.UncheckedRaised);

checkBox.IsChecked = false;

Assert.AreEqual(1, Binding_Static_Event_DataTemplate_Model_Class.CheckedRaised);
Assert.AreEqual(1, Binding_Static_Event_DataTemplate_Model_Class.UncheckedRaised);
}

[TestMethod]
public void When_Event_Nested_DataTemplate()
{
Expand Down

0 comments on commit 487cc9e

Please sign in to comment.