diff --git a/src/SamplesApp/UITests.Shared/UITests.Shared.projitems b/src/SamplesApp/UITests.Shared/UITests.Shared.projitems
index b6b447e1640c..dc822501cdf3 100644
--- a/src/SamplesApp/UITests.Shared/UITests.Shared.projitems
+++ b/src/SamplesApp/UITests.Shared/UITests.Shared.projitems
@@ -97,6 +97,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
@@ -2107,6 +2111,7 @@
Localization_Implicit.xaml
+
@@ -3705,6 +3710,9 @@
XamlGlobalResources.xaml
+
+ XamlLocalResources.xaml
+
diff --git a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/Resources/XamlLocalResources.xaml b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/Resources/XamlLocalResources.xaml
new file mode 100644
index 000000000000..c6c2709a6b8a
--- /dev/null
+++ b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/Resources/XamlLocalResources.xaml
@@ -0,0 +1,19 @@
+
+
+
+
+ Blue
+
+
+
+
+
diff --git a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/Resources/XamlLocalResources.xaml.cs b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/Resources/XamlLocalResources.xaml.cs
new file mode 100644
index 000000000000..982d6b2ff6a6
--- /dev/null
+++ b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/Resources/XamlLocalResources.xaml.cs
@@ -0,0 +1,18 @@
+using Windows.UI.Xaml.Controls;
+using Uno.UI.Samples.Controls;
+
+namespace UITests.Shared.Windows_UI_Xaml.Resources
+{
+ public sealed partial class XamlLocalResources : Page
+ {
+ public XamlLocalResources()
+ {
+ this.InitializeComponent();
+ }
+ }
+
+ internal class CustomTemplateSelector : DataTemplateSelector
+ {
+
+ }
+}
diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs
index 7877f2397732..dc4427becebc 100644
--- a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs
+++ b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs
@@ -4,6 +4,7 @@
using Uno.UI.SourceGenerators.XamlGenerator.Utils;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -73,6 +74,7 @@ internal partial class XamlFileGenerator
private readonly INamedTypeSymbol _stringSymbol;
private readonly INamedTypeSymbol _objectSymbol;
private readonly INamedTypeSymbol _iFrameworkElementSymbol;
+ private readonly INamedTypeSymbol _dependencyObjectSymbol;
private readonly INamedTypeSymbol _iCollectionSymbol;
private readonly INamedTypeSymbol _iCollectionOfTSymbol;
@@ -80,6 +82,7 @@ internal partial class XamlFileGenerator
private readonly INamedTypeSymbol _iListOfTSymbol;
private readonly INamedTypeSymbol _iDictionaryOfTKeySymbol;
private readonly INamedTypeSymbol _dataBindingSymbol;
+ private readonly INamedTypeSymbol _styleSymbol;
private readonly bool _isWasm;
@@ -130,12 +133,14 @@ bool isDebug
_elementStubSymbol = GetType(XamlConstants.Types.ElementStub);
_contentPresenterSymbol = GetType(XamlConstants.Types.ContentPresenter);
_iFrameworkElementSymbol = GetType(XamlConstants.Types.IFrameworkElement);
+ _dependencyObjectSymbol = GetType(XamlConstants.Types.DependencyObject);
_iCollectionSymbol = GetType("System.Collections.ICollection");
_iCollectionOfTSymbol = GetType("System.Collections.Generic.ICollection`1");
_iListSymbol = GetType("System.Collections.IList");
_iListOfTSymbol = GetType("System.Collections.Generic.IList`1");
_iDictionaryOfTKeySymbol = GetType("System.Collections.Generic.IDictionary`2");
_dataBindingSymbol = GetType("Windows.UI.Xaml.Data.Binding");
+ _styleSymbol = GetType(XamlConstants.Types.Style);
_isWasm = isWasm;
}
@@ -855,20 +860,39 @@ IEnumerable> namedResources
writer.AppendLineInvariant(0, ";", namedResource.Value.Type);
}
- // Styles are handled differently for now, and there's no variable generated
- // for those entries. Skip the ApplyCompiledBindings for those. See
- // ImportResourceDictionary handling of x:Name for more details.
- var namedResourcesExcludingStyles = namedResources
- .Where(nr => nr.Value.Type.Name.Equals("Style", StringComparison.Ordinal))
+ bool IsGenerateCompiledBindings(KeyValuePair nr)
+ {
+ var type = GetType(nr.Value.Type);
+
+ // Styles are handled differently for now, and there's no variable generated
+ // for those entries. Skip the ApplyCompiledBindings for those. See
+ // ImportResourceDictionary handling of x:Name for more details.
+ if (type.Equals(_styleSymbol))
+ {
+ return false;
+ }
+
+ if (type.AllInterfaces.Any(i => i.Equals(_dependencyObjectSymbol)))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ var resourcesTogenerateApplyCompiledBindings = namedResources
+ .Where(IsGenerateCompiledBindings)
.ToArray();
- if (namedResourcesExcludingStyles.Any())
+ if (resourcesTogenerateApplyCompiledBindings.Any())
{
using (writer.BlockInvariant("Loading += (s, e) =>"))
{
- foreach (var namedResource in namedResourcesExcludingStyles)
+ foreach (var namedResource in resourcesTogenerateApplyCompiledBindings)
{
- writer.AppendFormatInvariant($"{namedResource.Key}.ApplyCompiledBindings();");
+ var type = GetType(namedResource.Value.Type);
+
+ writer.AppendLineInvariant($"{namedResource.Key}.ApplyCompiledBindings();");
}
}
writer.AppendLineInvariant(0, ";");
@@ -962,7 +986,7 @@ IEnumerable> keyedResources
}
else
{
- // If there is no method suffix,
+ // If there is no method suffix,
using (writer.BlockInvariant("public static object FindResource(string name)"))
{
BuildGetResources(writer, keyedResources);
@@ -1678,7 +1702,7 @@ private void RegisterResources(XamlObjectDefinition topLevelControl)
if (isExplicitResDictionary)
{
- // To be able to have MergedDictionaries, the first node of the Resource node
+ // To be able to have MergedDictionaries, the first node of the Resource node
// must be an explicit resource dictionary.
resourcesMember = FindImplicitContentMember(resourcesMember.Objects.First());
@@ -1731,8 +1755,8 @@ private void TryExtractAutomationId(XamlMemberDefinition member, string[] target
var fullMemberName = $"{FindType(member.Member.DeclaringType)?.GetFullMetadataName()}.{member.Member.Name}";
- // Try to match each potential candidate by comparing based only on the name of the member first.
- // If that fails, try matching based on the full metadata name of the member
+ // Try to match each potential candidate by comparing based only on the name of the member first.
+ // If that fails, try matching based on the full metadata name of the member
var hasUiAutomationMapping = targetMembers
.Any(candidateMember =>
(!candidateMember.Contains(".") && candidateMember == member.Member.Name) ||
@@ -1752,7 +1776,7 @@ private void TryExtractAutomationId(XamlMemberDefinition member, string[] target
string bindingPath;
- // Checks the first binding member, which can be used to implicitlty declare the binding path (i.e. without
+ // Checks the first binding member, which can be used to implicitlty declare the binding path (i.e. without
// declaring a "Path=" specifier). Otherwise, the we look for any explicit binding path declaration.
var firstBindingMember = bindingMembers?.FirstOrDefault();
if (firstBindingMember != null &&
@@ -2162,7 +2186,7 @@ private void TryValidateContentPresenterBinding(IIndentedStringBuilder writer, X
var hasRelativeSource = binding.Members
.Any(m =>
m.Member.Name == "RelativeSource"
- // It can either be TemplatedParent or Self. In either cases, it does not use the inherited
+ // It can either be TemplatedParent or Self. In either cases, it does not use the inherited
// DataContext, which falls outside of the scenario we want to avoid.
);
@@ -2229,9 +2253,9 @@ private XamlLazyApplyBlockIIndentedStringBuilder CreateApplyBlock(IIndentedStrin
closureName = "c" + (_applyIndex++).ToString(CultureInfo.InvariantCulture);
//
- // Since we're using strings to generate the code, we can't know ahead of time if
+ // Since we're using strings to generate the code, we can't know ahead of time if
// content will be generated only by looking at the Xaml object model.
- // For now, we only observe if the inner code has generated code, and we create
+ // For now, we only observe if the inner code has generated code, and we create
// the apply block at that time.
//
string delegateType = null;
@@ -2604,7 +2628,7 @@ private string BuildLiteralValue(INamedTypeSymbol propertyType, string memberVal
throw new Exception("Unable to convert {0} for {1} with type {2}".InvariantCultureFormat(memberValue, memberName, propertyType));
}
-
+
private string BuildLocalizedResourceValue(XamlMemberDefinition owner, string memberName, string objectUid)
{
var uidParts = objectUid.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
@@ -3028,7 +3052,7 @@ private void BuildLiteralProperties(IIndentedStringBuilder writer, XamlObjectDef
}
else if (member.Member.DeclaringType == null && member.Member.Name == "Name")
{
- // This is a special case, where the declaring type is from the x: namespace,
+ // This is a special case, where the declaring type is from the x: namespace,
// but is considered of an unknown type. This can happen when providing the
// name of a control using x:Name instead of Name.
var hasNameProperty = HasProperty(objectDefinition.Type, "Name");
@@ -3195,7 +3219,7 @@ private void BuildChild(IIndentedStringBuilder writer, XamlMemberDefinition owne
if (contentOwner != null)
{
- // This case is to support the layout switching for the ListViewBaseLayout, which is not
+ // This case is to support the layout switching for the ListViewBaseLayout, which is not
// a FrameworkTemplate. Thsi will need to be removed when this custom list view is removed.
var returnType = typeName == "ListViewBaseLayoutTemplate" ? "Uno.UI.Controls.Legacy.ListViewBaseLayout" : "_View";
@@ -3294,7 +3318,7 @@ private void BuildChild(IIndentedStringBuilder writer, XamlMemberDefinition owne
}
}
- // Attached properties need to be expanded using the namespace, otherwise the resolution will be
+ // Attached properties need to be expanded using the namespace, otherwise the resolution will be
// performed at runtime at a higher cost.
propertyName = RewriteAttachedPropertyPath(propertyName);
diff --git a/src/Uno.UI/UI/Xaml/DependencyObjectExtensions.cs b/src/Uno.UI/UI/Xaml/DependencyObjectExtensions.cs
index 2d798123a152..59280b83de53 100644
--- a/src/Uno.UI/UI/Xaml/DependencyObjectExtensions.cs
+++ b/src/Uno.UI/UI/Xaml/DependencyObjectExtensions.cs
@@ -292,7 +292,7 @@ internal static IDisposable RegisterDisposableNestedPropertyChangedCallback(this
/// Register for changes all dependency properties changes notifications for the specified instance.
///
/// The instance for which to observe properties changes
- /// The callback
+ /// The callback
/// A disposable that will unregister the callback when disposed.
internal static IDisposable RegisterInheritedPropertyChangedCallback(this object instance, ExplicitPropertyChangedCallback handler)
{
@@ -300,10 +300,10 @@ internal static IDisposable RegisterInheritedPropertyChangedCallback(this object
}
///
- /// Register for compiled bindinds updates progapation
+ /// Register for compiled bindings updates propagation
///
/// The instance for which to observe compiled bindings updates
- /// The callback
+ /// The callback
/// A disposable that will unregister the callback when disposed.
internal static IDisposable RegisterCompiledBindingsUpdateCallback(this object instance, Action handler)
=> GetStore(instance).RegisterCompiledBindingsUpdateCallback(handler);
@@ -312,8 +312,8 @@ internal static IDisposable RegisterCompiledBindingsUpdateCallback(this object i
/// Registers to parent changes.
///
/// The target dependency object
- /// A key to be passed to the callack parameter.
- /// A callback to be called
+ /// A key to be passed to the callback parameter.
+ /// A callback to be called
/// A disposable that cancels the subscription.
internal static IDisposable RegisterParentChangedCallback(this DependencyObject instance, object key, ParentChangedCallback handler)
{