Skip to content

Commit

Permalink
fix: Fixed incorrect generation for xaml object binding with xaml obj…
Browse files Browse the repository at this point in the history
…ect properties.
  • Loading branch information
HavenDV committed Apr 4, 2022
1 parent 03c241a commit 90208b3
Show file tree
Hide file tree
Showing 6 changed files with 263 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4894,7 +4894,12 @@ private string BuildBindingOption(XamlMemberDefinition m, INamedTypeSymbol? prop

if (bindingType.Type.Name == "RelativeSource")
{
var resourceName = bindingType.Members.First().Value?.ToString();
var firstMember = bindingType.Members.First();
var resourceName = firstMember.Value?.ToString();
if (resourceName == null)
{
resourceName = firstMember.Objects.SingleOrDefault()?.Members?.SingleOrDefault()?.Value?.ToString();
}

return $"new RelativeSource(RelativeSourceMode.{resourceName})";
}
Expand All @@ -4904,63 +4909,80 @@ private string BuildBindingOption(XamlMemberDefinition m, INamedTypeSymbol? prop
return "null";
}

if (m.Member.Name == "TargetNullValue" && FindType(bindingType.Type) is INamedTypeSymbol namedTypeSymbol &&
m.Objects.SingleOrDefault()?.Members?.SingleOrDefault()?.Value is { } value)
{
return BuildLiteralValue(namedTypeSymbol, value.ToString());
}

if (IsCustomMarkupExtensionType(bindingType.Type))
{
return GetCustomMarkupExtensionValue(m);
}

// If type specified in the binding was not found, log and return an error message
if (!string.IsNullOrEmpty(bindingType.Type.Name))
if (memberName == "Converter" &&
m.Objects.SingleOrDefault() is XamlObjectDefinition { } converterObjectDefinition)
{
var message = $"#Error // {bindingType.Type.Name} could not be found.";
var fullTypeName = converterObjectDefinition.Type.Name;
var knownType = FindType(converterObjectDefinition.Type);
if (knownType == null && converterObjectDefinition.Type.PreferredXamlNamespace.StartsWith("using:"))
{
fullTypeName = converterObjectDefinition.Type.PreferredXamlNamespace.TrimStart("using:") + "." + converterObjectDefinition.Type.Name;
}
if (knownType != null)
{
// Override the using with the type that was found in the list of loaded assemblies
fullTypeName = knownType.ToDisplayString();
}

return message;
return $"new {GetGlobalizedTypeName(fullTypeName)}()";
}

return "#Error";
}
else
{

var value = BuildLiteralValue(m, GetPropertyType("Binding", memberName));

if (memberName == "Path")
if (FindType(bindingType.Type) is INamedTypeSymbol namedTypeSymbol &&
m.Objects.SingleOrDefault()?.Members?.SingleOrDefault() is XamlMemberDefinition { } innerMember)
{
value = RewriteAttachedPropertyPath(value);
m = innerMember;
}
else if (memberName == "ElementName")
else
{
if (m.Value == null)
// If type specified in the binding was not found, log and return an error message
if (!string.IsNullOrEmpty(bindingType.Type.Name))
{
throw new InvalidOperationException($"The property ElementName cannot be empty");
var message = $"null\r\n#error Invalid binding: {bindingType.Type.Name} could not be found.\r\n";

return message;
}

// Skip the literal value, use the elementNameSubject instead
string elementName = m.Value.ToString() ?? "";
value = "_" + elementName + "Subject";
// Track referenced ElementNames
CurrentScope.ReferencedElementNames.Add(elementName);
return $"null\r\n#error Invalid binding. Location: ({m.LineNumber}, {m.LinePosition})\r\n";
}
else if (memberName == "FallbackValue"
|| (memberName == "TargetNullValue"
&& m.Owner != null
&& m.Owner.Members.None(otherMember => otherMember.Member.Name == "Converter")))
}

var value = BuildLiteralValue(m, GetPropertyType("Binding", memberName));

if (memberName == "Path")
{
value = RewriteAttachedPropertyPath(value);
}
else if (memberName == "ElementName")
{
if (m.Value == null)
{
// FallbackValue can match the type of the property being bound.
// TargetNullValue possibly doesn't match the type of the property being bound,
// if there is a converter
value = BuildLiteralValue(m, propertyType);
throw new InvalidOperationException($"The property ElementName cannot be empty");
}


return value;
// Skip the literal value, use the elementNameSubject instead
string elementName = m.Value.ToString() ?? "";
value = "_" + elementName + "Subject";
// Track referenced ElementNames
CurrentScope.ReferencedElementNames.Add(elementName);
}
else if (memberName == "FallbackValue"
|| (memberName == "TargetNullValue"
&& m.Owner != null
&& m.Owner.Members.None(otherMember => otherMember.Member.Name == "Converter")))
{
// FallbackValue can match the type of the property being bound.
// TargetNullValue possibly doesn't match the type of the property being bound,
// if there is a converter
value = BuildLiteralValue(m, propertyType);
}


return value;
}

private string RewriteAttachedPropertyPath(string value)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<Page
x:Class="Uno.UI.Tests.Windows_UI_Xaml_Data.BindingTests.Controls.Binding_Xaml_Object_With_Common_Properties"
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>
<local:Binding_Xaml_Object_With_Common_Properties_Return_Value_Converter x:Key="Binding_Xaml_Object_With_Common_Properties_Return_Value_Converter" />
</Page.Resources>
<Grid>
<TextBlock
x:Name="topLevel"
x:FieldModifier="public"
Tag="42"
>
<TextBlock.Text>
<Binding
Path="Tag"
ElementName="topLevel"
Converter="{StaticResource Binding_Xaml_Object_With_Common_Properties_Return_Value_Converter}"
ConverterParameter="topLevel"
ConverterLanguage="topLevel"
UpdateSourceTrigger="Default"
TargetNullValue="TargetNullValue"
FallbackValue="FallbackValue"
Mode="OneWay"
RelativeSource="{RelativeSource Mode=None}"
Source="Source"
/>
</TextBlock.Text>
</TextBlock>
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
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_Xaml_Object_With_Common_Properties : Page
{
public Binding_Xaml_Object_With_Common_Properties()
{
this.InitializeComponent();
}
}

public sealed class Binding_Xaml_Object_With_Common_Properties_Return_Value_Converter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return value;
}

public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return value;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<Page
x:Class="Uno.UI.Tests.Windows_UI_Xaml_Data.BindingTests.Controls.Binding_Xaml_Object_With_Xaml_Object_Properties"
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>
<TextBlock
x:Name="topLevel"
x:FieldModifier="public"
Tag="42"
>
<TextBlock.Text>
<Binding>
<Binding.Path>
<PropertyPath>Tag</PropertyPath>
</Binding.Path>
<Binding.ElementName>
<x:String>topLevel</x:String>
</Binding.ElementName>
<Binding.Converter>
<local:Binding_Xaml_Object_With_Xaml_Object_Properties_Return_Value_Converter />
</Binding.Converter>
<Binding.ConverterParameter>
<x:String>topLevel</x:String>
</Binding.ConverterParameter>
<Binding.ConverterLanguage>
<x:String>topLevel</x:String>
</Binding.ConverterLanguage>
<Binding.UpdateSourceTrigger>
<UpdateSourceTrigger>Default</UpdateSourceTrigger>
</Binding.UpdateSourceTrigger>
<Binding.TargetNullValue>
<x:String>TargetNullValue</x:String>
</Binding.TargetNullValue>
<Binding.FallbackValue>
<x:String>FallbackValue</x:String>
</Binding.FallbackValue>
<Binding.Mode>
<BindingMode>OneWay</BindingMode>
</Binding.Mode>
<Binding.RelativeSource>
<RelativeSource>
<RelativeSource.Mode>
<RelativeSourceMode>None</RelativeSourceMode>
</RelativeSource.Mode>
</RelativeSource>
</Binding.RelativeSource>
<Binding.Source>
<x:String>Source</x:String>
</Binding.Source>
</Binding>
</TextBlock.Text>
</TextBlock>
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
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_Xaml_Object_With_Xaml_Object_Properties : Page
{
public Binding_Xaml_Object_With_Xaml_Object_Properties()
{
this.InitializeComponent();
}
}

public sealed class Binding_Xaml_Object_With_Xaml_Object_Properties_Return_Value_Converter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return value;
}

public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return value;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,5 +131,25 @@ public void When_ElementName_In_Template_In_Template()

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

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

SUT.ForceLoaded();

Assert.AreEqual("42", SUT.topLevel.Text);
}

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

SUT.ForceLoaded();

Assert.AreEqual("42", SUT.topLevel.Text);
}
}
}

0 comments on commit 90208b3

Please sign in to comment.