diff --git a/build/PackageDiffIgnore.xml b/build/PackageDiffIgnore.xml
index cde7c0efdf04..0113851ecedc 100644
--- a/build/PackageDiffIgnore.xml
+++ b/build/PackageDiffIgnore.xml
@@ -1910,11 +1910,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/SourceGenerators/System.Xaml.Tests/Test/System.Xaml/XamlXmlReaderTest.cs b/src/SourceGenerators/System.Xaml.Tests/Test/System.Xaml/XamlXmlReaderTest.cs
index f24ae58f0a09..e2a7db8e47ae 100644
--- a/src/SourceGenerators/System.Xaml.Tests/Test/System.Xaml/XamlXmlReaderTest.cs
+++ b/src/SourceGenerators/System.Xaml.Tests/Test/System.Xaml/XamlXmlReaderTest.cs
@@ -360,6 +360,7 @@ public void Read_GenericSimple()
[Test]
public void Read_GenericWithProperty()
{
+ const string not_win = "{http://uno.ui/not_win}";
var sequence = new SequenceItem[] {
new SequenceItem { NodeType = XamlNodeType.NamespaceDeclaration, },
new SequenceItem { NodeType = XamlNodeType.NamespaceDeclaration, },
@@ -382,16 +383,18 @@ public void Read_GenericWithProperty()
new SequenceItem { NodeType = XamlNodeType.EndMember, },
new SequenceItem { NodeType = XamlNodeType.StartMember, MemberType = "{http://schemas.microsoft.com/winfx/2006/xaml}_UnknownContent", },
- new SequenceItem { NodeType = XamlNodeType.StartObject, TypeName = "{http://schemas.microsoft.com/winfx/2006/xaml/presentation}Style"},
+ new SequenceItem { NodeType = XamlNodeType.StartObject, TypeName = $"{not_win}Style"},
new SequenceItem { NodeType = XamlNodeType.StartMember, MemberType = "{http://schemas.microsoft.com/winfx/2006/xaml}Key", },
new SequenceItem { NodeType = XamlNodeType.Value, Value = "DefaultComboBoxItemStyle", },
new SequenceItem { NodeType = XamlNodeType.EndMember, },
- new SequenceItem { NodeType = XamlNodeType.StartMember, MemberType = "{http://schemas.microsoft.com/winfx/2006/xaml/presentation}Style.OtherProperty", },
+ new SequenceItem { NodeType = XamlNodeType.StartMember, MemberType = $"{not_win}Style.OtherProperty", },
new SequenceItem { NodeType = XamlNodeType.Value, Value = "test", },
new SequenceItem { NodeType = XamlNodeType.EndMember, },
+#if false // XamlXmlReader fails to read any xmlns'd node/attribute with invalid uri (such as a guid or 'using:System.Somewhere')
new SequenceItem { NodeType = XamlNodeType.StartMember, MemberType = "{http://schemas.microsoft.com/winfx/2006/xaml/presentation}Style.TargetType", },
new SequenceItem { NodeType = XamlNodeType.Value, Value = "SelectorItem", },
new SequenceItem { NodeType = XamlNodeType.EndMember, },
+#endif
new SequenceItem { NodeType = XamlNodeType.EndObject, },
new SequenceItem { NodeType = XamlNodeType.EndMember, },
new SequenceItem { NodeType = XamlNodeType.EndObject, },
@@ -2507,9 +2510,30 @@ public void Bug680385 ()
}
#endregion
+ private string GetXml(string fileName)
+ {
+ var directory = Path.GetDirectoryName(new Uri(GetType().Assembly.CodeBase).LocalPath);
+ var path = Path.Combine(directory, "Test/XmlFiles", fileName);
+
+ return File.ReadAllText(path).Replace("System.Xaml_test_net_4_0", "Uno.Xaml.Tests");
+ }
+
+ private IEnumerable<(XamlNodeType, string, string, object, string)> ReadAllTokens(string fileName)
+ {
+ var r = GetReader(fileName);
+ int i = 0;
+ while (r.Read())
+ {
+ yield return (r.NodeType, r.Member?.ToString(), r.Member?.Name, r.Value, r.Type?.ToString());
+ }
+ }
+
private void ReadSequence(string fileName, IEnumerable sequence)
{
- //ReadTest(fileName);
+#if DEBUG && false
+ var xml = GetXml(fileName);
+ var tokens = ReadAllTokens(fileName).ToArray();
+#endif
var r = GetReader(fileName);
diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/DependencyObjectGeneratorTests/Given_DependencyObjectGenerator.cs b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/DependencyObjectGeneratorTests/Given_DependencyObjectGenerator.cs
index 50d5372af071..731110a9ed7e 100644
--- a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/DependencyObjectGeneratorTests/Given_DependencyObjectGenerator.cs
+++ b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/DependencyObjectGeneratorTests/Given_DependencyObjectGenerator.cs
@@ -143,6 +143,7 @@ internal partial class Inner : DependencyObject
using System.Linq;
using System.Collections.Generic;
using System.Collections;
+ using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using Uno.Disposables;
using System.Runtime.CompilerServices;
@@ -158,7 +159,7 @@ internal partial class Inner : DependencyObject
partial class OuterClass
{
[global::Microsoft.UI.Xaml.Data.Bindable]
- partial class Inner : IDependencyObjectStoreProvider, IWeakReferenceProvider
+ partial class Inner : IDependencyObjectStoreProvider, ITemplatedParentProvider, IWeakReferenceProvider
{
private DependencyObjectStore __storeBackingField;
public global::Windows.UI.Core.CoreDispatcher Dispatcher => global::Windows.ApplicationModel.Core.CoreApplication.MainView.Dispatcher;
@@ -169,7 +170,7 @@ private DependencyObjectStore __Store
{
if(__storeBackingField == null)
{
- __storeBackingField = new DependencyObjectStore(this, DataContextProperty, TemplatedParentProperty);
+ __storeBackingField = new DependencyObjectStore(this, DataContextProperty);
__InitializeBinder();
}
return __storeBackingField;
@@ -184,6 +185,28 @@ private DependencyObjectStore __Store
public object GetAnimationBaseValue(DependencyProperty dp) => __Store.GetAnimationBaseValue(dp);
public long RegisterPropertyChangedCallback(DependencyProperty dp, DependencyPropertyChangedCallback callback) => __Store.RegisterPropertyChangedCallback(dp, callback);
public void UnregisterPropertyChangedCallback(DependencyProperty dp, long token) => __Store.UnregisterPropertyChangedCallback(dp, token);
+
+ [EditorBrowsable(EditorBrowsableState.Never)]private ManagedWeakReference _templatedParentWeakRef;
+ [EditorBrowsable(EditorBrowsableState.Never)]public ManagedWeakReference GetTemplatedParentWeakRef() => _templatedParentWeakRef;
+
+ [EditorBrowsable(EditorBrowsableState.Never)]public DependencyObject GetTemplatedParent() => _templatedParentWeakRef?.Target as DependencyObject;
+ [EditorBrowsable(EditorBrowsableState.Never)]public void SetTemplatedParent(DependencyObject parent)
+ {
+ //if (parent != null)
+ //{
+ // global::System.Diagnostics.Debug.Assert(parent
+ // is global::Windows.UI.Xaml.Controls.Control
+ // or global::Windows.UI.Xaml.Controls.ContentPresenter
+ // or global::Windows.UI.Xaml.Controls.ItemsPresenter);
+ // global::System.Diagnostics.Debug.Assert(GetTemplatedParent() == null);
+ //}
+
+ SetTemplatedParentImpl(parent);
+ }
+ [EditorBrowsable(EditorBrowsableState.Never)]private protected virtual void SetTemplatedParentImpl(DependencyObject parent)
+ {
+ _templatedParentWeakRef = (parent as IWeakReferenceProvider)?.WeakReference;
+ }
private readonly static IEventProvider _binderTrace = Tracing.Get(DependencyObjectStore.TraceProvider.Id);
private BinderReferenceHolder _refHolder;
@@ -266,15 +289,16 @@ internal protected virtual void OnDataContextChanged(DependencyPropertyChangedEv
#endregion
- #region TemplatedParent DependencyProperty
+ #region TemplatedParent DependencyProperty // legacy api, should no longer to be used.
- public DependencyObject TemplatedParent
+ [EditorBrowsable(EditorBrowsableState.Never)]public DependencyObject TemplatedParent
{
get => (DependencyObject)GetValue(TemplatedParentProperty);
set => SetValue(TemplatedParentProperty, value);
}
// Using a DependencyProperty as the backing store for TemplatedParent. This enables animation, styling, binding, etc...
+ [EditorBrowsable(EditorBrowsableState.Never)]
public static DependencyProperty TemplatedParentProperty { get ; } =
DependencyProperty.Register(
name: nameof(TemplatedParent),
@@ -282,15 +306,15 @@ public DependencyObject TemplatedParent
ownerType: typeof(Inner),
typeMetadata: new FrameworkPropertyMetadata(
defaultValue: null,
- options: FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.ValueDoesNotInheritDataContext | FrameworkPropertyMetadataOptions.WeakStorage,
+ options: /*FrameworkPropertyMetadataOptions.Inherits | */FrameworkPropertyMetadataOptions.ValueDoesNotInheritDataContext | FrameworkPropertyMetadataOptions.WeakStorage,
propertyChangedCallback: (s, e) => ((Inner)s).OnTemplatedParentChanged(e)
)
);
+ [EditorBrowsable(EditorBrowsableState.Never)]
internal protected virtual void OnTemplatedParentChanged(DependencyPropertyChangedEventArgs e)
{
- __Store.SetTemplatedParent(e.NewValue as FrameworkElement);
OnTemplatedParentChangedPartial(e);
}
@@ -321,6 +345,7 @@ public void SetBindingValue(object value, [CallerMemberName] string propertyName
partial void OnDataContextChangedPartial(DependencyPropertyChangedEventArgs e);
+ [EditorBrowsable(EditorBrowsableState.Never)]
partial void OnTemplatedParentChangedPartial(DependencyPropertyChangedEventArgs e);
public global::Microsoft.UI.Xaml.Data.BindingExpression GetBindingExpression(DependencyProperty dependencyProperty)
diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/SOSLIIOFDOTAFE/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/SOSLIIOFDOTAFE/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs
index dd263452a3de..d1e437382bdd 100644
--- a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/SOSLIIOFDOTAFE/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs
+++ b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/SOSLIIOFDOTAFE/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs
@@ -111,7 +111,7 @@ private void InitializeComponent()
"MyItemTemplate"
] =
new global::Uno.UI.Xaml.WeakResourceInitializer(this, __ResourceOwner_1 =>
- new global::Microsoft.UI.Xaml.DataTemplate(__ResourceOwner_1 , __owner => ((I_MainPage_d6cd66944958ced0c513e0a04797b51d_TestReproMainPageSC0)global::Uno.UI.Helpers.TypeMappings.CreateInstance<_MainPage_d6cd66944958ced0c513e0a04797b51d_TestReproMainPageSC0>()).Build(__owner)
+ new global::Microsoft.UI.Xaml.DataTemplate(__ResourceOwner_1, (__owner) => ((I_MainPage_d6cd66944958ced0c513e0a04797b51d_TestReproMainPageSC0)global::Uno.UI.Helpers.TypeMappings.CreateInstance<_MainPage_d6cd66944958ced0c513e0a04797b51d_TestReproMainPageSC0>()).Build(__owner)
) .GenericApply(__that, __nameScope, ((c6, __that, __nameScope) =>
{
global::Uno.UI.Helpers.MarkupHelper.SetElementProperty(c6, "OriginalSourceLocation", "file:///C:/Project/0/MainPage.xaml#L13:6");
@@ -125,7 +125,7 @@ private void InitializeComponent()
{
IsParsing = true,
Name = "TheListView",
- HeaderTemplate = new global::Microsoft.UI.Xaml.DataTemplate(this , __owner => ((I_MainPage_d6cd66944958ced0c513e0a04797b51d_TestReproMainPageSC1)global::Uno.UI.Helpers.TypeMappings.CreateInstance<_MainPage_d6cd66944958ced0c513e0a04797b51d_TestReproMainPageSC1>()).Build(__owner)
+ HeaderTemplate = new global::Microsoft.UI.Xaml.DataTemplate(this, (__owner) => ((I_MainPage_d6cd66944958ced0c513e0a04797b51d_TestReproMainPageSC1)global::Uno.UI.Helpers.TypeMappings.CreateInstance<_MainPage_d6cd66944958ced0c513e0a04797b51d_TestReproMainPageSC1>()).Build(__owner)
) .GenericApply(__that, __nameScope, ((c7, __that, __nameScope) =>
{
global::Uno.UI.Helpers.MarkupHelper.SetElementProperty(c7, "OriginalSourceLocation", "file:///C:/Project/0/MainPage.xaml#L42:8");
diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/SOSLIOFPLR/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/SOSLIOFPLR/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs
index f0729493fa25..abb1c12d4419 100644
--- a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/SOSLIOFPLR/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs
+++ b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/SOSLIOFPLR/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs
@@ -111,7 +111,7 @@ private void InitializeComponent()
"MyItemTemplate"
] =
new global::Uno.UI.Xaml.WeakResourceInitializer(this, __ResourceOwner_1 =>
- new global::Microsoft.UI.Xaml.DataTemplate(__ResourceOwner_1 , __owner => ((I_MainPage_d6cd66944958ced0c513e0a04797b51d_TestReproMainPageSC0)global::Uno.UI.Helpers.TypeMappings.CreateInstance<_MainPage_d6cd66944958ced0c513e0a04797b51d_TestReproMainPageSC0>()).Build(__owner)
+ new global::Microsoft.UI.Xaml.DataTemplate(__ResourceOwner_1, (__owner) => ((I_MainPage_d6cd66944958ced0c513e0a04797b51d_TestReproMainPageSC0)global::Uno.UI.Helpers.TypeMappings.CreateInstance<_MainPage_d6cd66944958ced0c513e0a04797b51d_TestReproMainPageSC0>()).Build(__owner)
) .GenericApply(__that, __nameScope, ((c6, __that, __nameScope) =>
{
global::Uno.UI.Helpers.MarkupHelper.SetElementProperty(c6, "OriginalSourceLocation", "file:///C:/Project/0/MainPage.xaml#L13:6");
diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TDBMIDTIRD/XamlCodeGenerator_MyResourceDictionary_92716e07ff456818f6d4125e055d4d57.cs b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TDBMIDTIRD/XamlCodeGenerator_MyResourceDictionary_92716e07ff456818f6d4125e055d4d57.cs
index f6ba8f64b66c..a6e3e15cbe04 100644
--- a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TDBMIDTIRD/XamlCodeGenerator_MyResourceDictionary_92716e07ff456818f6d4125e055d4d57.cs
+++ b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TDBMIDTIRD/XamlCodeGenerator_MyResourceDictionary_92716e07ff456818f6d4125e055d4d57.cs
@@ -46,7 +46,7 @@ public void InitializeComponent()
"myTemplate"
] =
new global::Uno.UI.Xaml.WeakResourceInitializer(this, __ResourceOwner_1 =>
- new global::Microsoft.UI.Xaml.DataTemplate(__ResourceOwner_1 , __owner => new _MyResourceDictionary_92716e07ff456818f6d4125e055d4d57_TestReproMyResourceDictionarySC0().Build(__owner)
+ new global::Microsoft.UI.Xaml.DataTemplate(__ResourceOwner_1, (__owner) => new _MyResourceDictionary_92716e07ff456818f6d4125e055d4d57_TestReproMyResourceDictionarySC0().Build(__owner)
) )
;
}
@@ -178,7 +178,7 @@ public ResourceDictionarySingleton__MyResourceDictionary_92716e07ff456818f6d4125
// Method for resource myTemplate
private object Get_1(object __ResourceOwner_1) =>
- new global::Microsoft.UI.Xaml.DataTemplate(__ResourceOwner_1 , __owner => new __Resources._MyResourceDictionary_92716e07ff456818f6d4125e055d4d57_MyResourceDictionaryRDSC1().Build(__owner)
+ new global::Microsoft.UI.Xaml.DataTemplate(__ResourceOwner_1, (__owner) => new __Resources._MyResourceDictionary_92716e07ff456818f6d4125e055d4d57_MyResourceDictionaryRDSC1().Build(__owner)
) ;
private global::Microsoft.UI.Xaml.ResourceDictionary _MyResourceDictionary_92716e07ff456818f6d4125e055d4d57_ResourceDictionary;
@@ -197,7 +197,7 @@ private object Get_1(object __ResourceOwner_1) =>
"myTemplate"
] =
new global::Uno.UI.Xaml.WeakResourceInitializer(this, __ResourceOwner_1 =>
- new global::Microsoft.UI.Xaml.DataTemplate(__ResourceOwner_1 , __owner => new __Resources._MyResourceDictionary_92716e07ff456818f6d4125e055d4d57_MyResourceDictionaryRDSC2().Build(__owner)
+ new global::Microsoft.UI.Xaml.DataTemplate(__ResourceOwner_1, (__owner) => new __Resources._MyResourceDictionary_92716e07ff456818f6d4125e055d4d57_MyResourceDictionaryRDSC2().Build(__owner)
) )
,
}
diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TTIXLE/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TTIXLE/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs
index 3c3a8c59ae5b..85a7f0b01019 100644
--- a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TTIXLE/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs
+++ b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TTIXLE/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs
@@ -99,7 +99,7 @@ private void InitializeComponent()
{
IsParsing = true,
Name = "inner2",
- Template = new global::Microsoft.UI.Xaml.Controls.ControlTemplate(this , __owner => new _MainPage_d6cd66944958ced0c513e0a04797b51d_TestReproMainPageSC0().Build(__owner)
+ Template = new global::Microsoft.UI.Xaml.Controls.ControlTemplate(this, (__owner) => new _MainPage_d6cd66944958ced0c513e0a04797b51d_TestReproMainPageSC0().Build(__owner)
) ,
// Source 0\MainPage.xaml (Line 15:5)
}
diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/WBENIT/XamlCodeGenerator_Binding_ElementName_In_Template_66bf0a54f1801c397a6fa4930a237eca.cs b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/WBENIT/XamlCodeGenerator_Binding_ElementName_In_Template_66bf0a54f1801c397a6fa4930a237eca.cs
index 2bfcbd8de737..df6fde489dbb 100644
--- a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/WBENIT/XamlCodeGenerator_Binding_ElementName_In_Template_66bf0a54f1801c397a6fa4930a237eca.cs
+++ b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/WBENIT/XamlCodeGenerator_Binding_ElementName_In_Template_66bf0a54f1801c397a6fa4930a237eca.cs
@@ -59,7 +59,7 @@ private void InitializeComponent()
IsParsing = true,
Name = "topLevel",
Tag = @"42",
- ContentTemplate = new global::Microsoft.UI.Xaml.DataTemplate(this , __owner => new _Binding_ElementName_In_Template_66bf0a54f1801c397a6fa4930a237eca_UnoUITestsWindows_UI_Xaml_DataBindingTestsControlsBinding_ElementName_In_TemplateSC0().Build(__owner)
+ ContentTemplate = new global::Microsoft.UI.Xaml.DataTemplate(this, (__owner) => new _Binding_ElementName_In_Template_66bf0a54f1801c397a6fa4930a237eca_UnoUITestsWindows_UI_Xaml_DataBindingTestsControlsBinding_ElementName_In_TemplateSC0().Build(__owner)
) ,
// Source 0\Binding_ElementName_In_Template.xaml (Line 11:4)
}
diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/DependencyObject/DependencyObjectGenerator.cs b/src/SourceGenerators/Uno.UI.SourceGenerators/DependencyObject/DependencyObjectGenerator.cs
index 84eaa4bba263..059614e4d766 100644
--- a/src/SourceGenerators/Uno.UI.SourceGenerators/DependencyObject/DependencyObjectGenerator.cs
+++ b/src/SourceGenerators/Uno.UI.SourceGenerators/DependencyObject/DependencyObjectGenerator.cs
@@ -153,6 +153,7 @@ private void ProcessType(INamedTypeSymbol typeSymbol)
using System.Linq;
using System.Collections.Generic;
using System.Collections;
+using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using Uno.Disposables;
using System.Runtime.CompilerServices;
@@ -174,10 +175,18 @@ private void ProcessType(INamedTypeSymbol typeSymbol)
}
};
- var internalDependencyObject = _isUnoSolution && !typeSymbol.IsSealed ? ", IDependencyObjectInternal" : "";
- using (typeSymbol.AddToIndentedStringBuilder(builder, beforeClassHeaderAction, afterClassHeader: $" : IDependencyObjectStoreProvider, IWeakReferenceProvider{internalDependencyObject}"))
+ var canBeTpProvider = !typeSymbol.Interfaces.Any(x => x.Name == "INotTemplatedParentProvider");
+
+ var implementations = new string?[]
+ {
+ "IDependencyObjectStoreProvider",
+ _isUnoSolution && !typeSymbol.IsSealed ? "IDependencyObjectInternal" : null,
+ canBeTpProvider ? "ITemplatedParentProvider" : null,
+ "IWeakReferenceProvider",
+ }.Where(x => x is not null);
+ using (typeSymbol.AddToIndentedStringBuilder(builder, beforeClassHeaderAction, afterClassHeader: " : " + string.Join(", ", implementations)))
{
- GenerateDependencyObjectImplementation(typeSymbol, builder, hasDispatcherQueue: _dependencyObjectSymbol!.GetMembers("DispatcherQueue").Any());
+ GenerateDependencyObjectImplementation(typeSymbol, builder, hasDispatcherQueue: _dependencyObjectSymbol!.GetMembers("DispatcherQueue").Any(), canBeTpProvider);
GenerateIBinderImplementation(typeSymbol, builder);
}
@@ -236,19 +245,9 @@ public override void WillMoveToSuperview(UIKit.UIView newsuper)
base.WillMoveToSuperview(newsuper);
WillMoveToSuperviewPartial(newsuper);
-
- SyncBinder(newsuper, Window);
}
partial void WillMoveToSuperviewPartial(UIKit.UIView newsuper);
-
-private void SyncBinder(UIKit.UIView superview, UIKit.UIWindow window)
-{
- if(superview == null && window == null)
- {
- TemplatedParent = null;
- }
-}
");
}
else
@@ -274,19 +273,9 @@ public override void ViewWillMoveToSuperview(AppKit.NSView newsuper)
base.ViewWillMoveToSuperview(newsuper);
WillMoveToSuperviewPartial(newsuper);
-
- SyncBinder(newsuper, Window);
}
partial void WillMoveToSuperviewPartial(AppKit.NSView newsuper);
-
-private void SyncBinder(AppKit.NSView superview, AppKit.NSWindow window)
-{
- if(superview == null && window == null)
- {
- TemplatedParent = null;
- }
-}
");
}
else
@@ -625,6 +614,8 @@ private void WriteBinderImplementation(INamedTypeSymbol typeSymbol, IndentedStri
{
var virtualModifier = typeSymbol.IsSealed ? "" : "virtual";
var protectedModifier = typeSymbol.IsSealed ? "private" : "internal protected";
+ var legacyNonBrowsable = "[EditorBrowsable(EditorBrowsableState.Never)]";
+
string dataContextChangedInvokeArgument;
if (typeSymbol.Is(_frameworkElementSymbol))
{
@@ -676,15 +667,16 @@ public object DataContext
#endregion
-#region TemplatedParent DependencyProperty
+#region TemplatedParent DependencyProperty // legacy api, should no longer to be used.
-public DependencyObject TemplatedParent
+{legacyNonBrowsable}public DependencyObject TemplatedParent
{{
get => (DependencyObject)GetValue(TemplatedParentProperty);
set => SetValue(TemplatedParentProperty, value);
}}
// Using a DependencyProperty as the backing store for TemplatedParent. This enables animation, styling, binding, etc...
+{legacyNonBrowsable}
public static DependencyProperty TemplatedParentProperty {{ get ; }} =
DependencyProperty.Register(
name: nameof(TemplatedParent),
@@ -692,15 +684,15 @@ public DependencyObject TemplatedParent
ownerType: typeof({typeSymbol.Name}),
typeMetadata: new FrameworkPropertyMetadata(
defaultValue: null,
- options: FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.ValueDoesNotInheritDataContext | FrameworkPropertyMetadataOptions.WeakStorage,
+ options: /*FrameworkPropertyMetadataOptions.Inherits | */FrameworkPropertyMetadataOptions.ValueDoesNotInheritDataContext | FrameworkPropertyMetadataOptions.WeakStorage,
propertyChangedCallback: (s, e) => (({typeSymbol.Name})s).OnTemplatedParentChanged(e)
)
);
+{legacyNonBrowsable}
{protectedModifier} {virtualModifier} void OnTemplatedParentChanged(DependencyPropertyChangedEventArgs e)
{{
- __Store.SetTemplatedParent(e.NewValue as FrameworkElement);
OnTemplatedParentChangedPartial(e);
}}
@@ -731,6 +723,7 @@ public void SetBindingValue(object value, [CallerMemberName] string propertyName
partial void OnDataContextChangedPartial(DependencyPropertyChangedEventArgs e);
+{legacyNonBrowsable}
partial void OnTemplatedParentChangedPartial(DependencyPropertyChangedEventArgs e);
public global::Microsoft.UI.Xaml.Data.BindingExpression GetBindingExpression(DependencyProperty dependencyProperty)
@@ -775,7 +768,7 @@ public override bool Equals(object other)
}
}
- private void GenerateDependencyObjectImplementation(INamedTypeSymbol typeSymbol, IndentedStringBuilder builder, bool hasDispatcherQueue)
+ private void GenerateDependencyObjectImplementation(INamedTypeSymbol typeSymbol, IndentedStringBuilder builder, bool hasDispatcherQueue, bool implTpProvider)
{
builder.AppendLineIndented(@"private DependencyObjectStore __storeBackingField;");
builder.AppendLineIndented(@"public global::Windows.UI.Core.CoreDispatcher Dispatcher => global::Windows.ApplicationModel.Core.CoreApplication.MainView.Dispatcher;");
@@ -791,7 +784,7 @@ private void GenerateDependencyObjectImplementation(INamedTypeSymbol typeSymbol,
{
using (builder.BlockInvariant($"if(__storeBackingField == null)"))
{
- builder.AppendLineIndented("__storeBackingField = new DependencyObjectStore(this, DataContextProperty, TemplatedParentProperty);");
+ builder.AppendLineIndented("__storeBackingField = new DependencyObjectStore(this, DataContextProperty);");
builder.AppendLineIndented("__InitializeBinder();");
}
@@ -825,6 +818,37 @@ private void GenerateDependencyObjectImplementation(INamedTypeSymbol typeSymbol,
builder.AppendLineIndented("internal virtual void OnPropertyChanged2(global::Microsoft.UI.Xaml.DependencyPropertyChangedEventArgs args) { }");
}
}
+
+ if (implTpProvider)
+ {
+ var unoBrowsableOnly = _isUnoSolution ? null : "[EditorBrowsable(EditorBrowsableState.Never)]";
+
+ builder.AppendLine();
+ builder.AppendMultiLineIndented($$"""
+ {{unoBrowsableOnly}}private ManagedWeakReference _templatedParentWeakRef;
+ {{unoBrowsableOnly}}public ManagedWeakReference GetTemplatedParentWeakRef() => _templatedParentWeakRef;
+
+ {{unoBrowsableOnly}}public DependencyObject GetTemplatedParent() => _templatedParentWeakRef?.Target as DependencyObject;
+ {{unoBrowsableOnly}}public void SetTemplatedParent(DependencyObject parent)
+ {
+ //if (parent != null)
+ //{
+ // global::System.Diagnostics.Debug.Assert(parent
+ // is global::Windows.UI.Xaml.Controls.Control
+ // or global::Windows.UI.Xaml.Controls.ContentPresenter
+ // or global::Windows.UI.Xaml.Controls.ItemsPresenter);
+ // global::System.Diagnostics.Debug.Assert(GetTemplatedParent() == null);
+ //}
+
+ SetTemplatedParentImpl(parent);
+ }
+ {{unoBrowsableOnly}}{{(typeSymbol.IsSealed ? "private" : "private protected virtual")}} void SetTemplatedParentImpl(DependencyObject parent)
+ {
+ _templatedParentWeakRef = (parent as IWeakReferenceProvider)?.WeakReference;
+ }
+ """
+ );
+ }
}
}
}
diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs
index 0dc4fa793265..9a762c4b2a5c 100644
--- a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs
+++ b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs
@@ -922,7 +922,11 @@ private void BuildChildSubclasses(IIndentedStringBuilder writer, bool isTopLevel
// implementation of a type during hot reload.
using (writer.BlockInvariant($"internal interface {hrInterfaceName}"))
{
+#if USE_NEW_TP_CODEGEN
+ writer.AppendLineIndented($"{kvp.Value.ReturnType} Build(object owner, global::Microsoft.UI.Xaml.TemplateMaterializationSettings __settings);");
+#else
writer.AppendLineIndented($"{kvp.Value.ReturnType} Build(object owner);");
+#endif
}
}
@@ -938,7 +942,11 @@ private void BuildChildSubclasses(IIndentedStringBuilder writer, bool isTopLevel
{
writer.AppendLineIndented("global::Microsoft.UI.Xaml.NameScope __nameScope = new global::Microsoft.UI.Xaml.NameScope();");
+#if USE_NEW_TP_CODEGEN
+ using (writer.BlockInvariant($"public {kvp.Value.ReturnType} Build(object {CurrentResourceOwner}, global::Microsoft.UI.Xaml.TemplateMaterializationSettings __settings)"))
+#else
using (writer.BlockInvariant($"public {kvp.Value.ReturnType} Build(object {CurrentResourceOwner})"))
+#endif
{
writer.AppendLineIndented($"{kvp.Value.ReturnType} __rootInstance = null;");
writer.AppendLineIndented($"var __that = this;");
@@ -951,9 +959,9 @@ private void BuildChildSubclasses(IIndentedStringBuilder writer, bool isTopLevel
BuildCompiledBindingsInitializerForTemplate(writer);
- using (writer.BlockInvariant("if (__rootInstance is DependencyObject d)", kvp.Value.ReturnType))
+ using (writer.BlockInvariant("if (__rootInstance is DependencyObject d)"))
{
- using (writer.BlockInvariant("if (global::Microsoft.UI.Xaml.NameScope.GetNameScope(d) == null)", kvp.Value.ReturnType))
+ using (writer.BlockInvariant("if (global::Microsoft.UI.Xaml.NameScope.GetNameScope(d) == null)"))
{
writer.AppendLineIndented("global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope);");
writer.AppendLineIndented("__nameScope.Owner = d;");
@@ -3064,13 +3072,22 @@ private void BuildExtendedProperties(IIndentedStringBuilder outerwriter, XamlObj
writer.AppendIndented(GenerateRootPhases(objectDefinition, closureName) ?? "");
}
+ var isInsideFrameworkTemplate = IsMemberInsideFrameworkTemplate(objectDefinition).isInside;
+#if USE_NEW_TP_CODEGEN
+ var isDependencyObject = IsType(objectDefinitionType, Generation.DependencyObjectSymbol.Value);
+ if (isInsideFrameworkTemplate && isDependencyObject)
+ {
+ writer.AppendLineIndented($"{closureName}.SetTemplatedParent(__settings?.TemplatedParent);");
+ writer.AppendLineIndented($"__settings?.TemplateMemberCreatedCallback?.Invoke({closureName});");
+ }
+#endif
+
componentDefinition = CurrentScope.Components.FirstOrDefault(x => x.XamlObject == objectDefinition);
if (componentDefinition is { } || // element can also be register for component by a descendant DO as its resource provider
HasXBindMarkupExtension(objectDefinition) ||
HasMarkupExtensionNeedingComponent(objectDefinition))
{
writer.AppendLineIndented($"/* _isTopLevelDictionary:{_isTopLevelDictionary} */");
- var isInsideFrameworkTemplate = IsMemberInsideFrameworkTemplate(objectDefinition).isInside;
if (!_isTopLevelDictionary || isInsideFrameworkTemplate)
{
componentDefinition ??= AddComponentForCurrentScope(objectDefinition);
@@ -5899,13 +5916,14 @@ private IEnumerable GetExtendedProperties(XamlObjectDefini
private static bool IsNewScope(XamlObjectDefinition xamlObjectDefinition)
{
- var typeName = xamlObjectDefinition.Type.Name;
- return typeName == "DataTemplate" ||
- typeName == "ItemsPanelTemplate" ||
- typeName == "ControlTemplate" ||
+ return xamlObjectDefinition.Type.Name
+ is "DataTemplate"
+ or "ItemsPanelTemplate"
+ or "ControlTemplate"
+
// This case is specific the custom ListView for iOS. Should be removed
// when the list rebuilt to be compatible.
- typeName == "ListViewBaseLayoutTemplate";
+ or "ListViewBaseLayoutTemplate";
}
private void BuildChild(IIndentedStringBuilder writer, XamlMemberDefinition? owner, XamlObjectDefinition xamlObjectDefinition, string? outerClosure = null)
@@ -5945,11 +5963,15 @@ private void BuildChild(IIndentedStringBuilder writer, XamlMemberDefinition? own
{
var resourceOwner = CurrentResourceOwnerName;
- writer.Append($"{resourceOwner} , __owner => ");
+#if USE_NEW_TP_CODEGEN
+ writer.Append($"{resourceOwner}, (__owner, __settings) => ");
+#else
+ writer.Append($"{resourceOwner}, (__owner) => ");
+#endif
+
// This case is to support the layout switching for the ListViewBaseLayout, which is not
// a FrameworkTemplate. This will need to be removed when this custom list view is removed.
var returnType = typeName == "ListViewBaseLayoutTemplate" ? "global::Uno.UI.Controls.Legacy.ListViewBaseLayout" : "_View";
-
BuildChildThroughSubclass(writer, contentOwner, returnType);
writer.AppendIndented(")");
@@ -6597,8 +6619,11 @@ private void BuildChildThroughSubclass(IIndentedStringBuilder writer, XamlMember
var activator = _isHotReloadEnabled
? $"(({namespacePrefix}I{subclassName})global::Uno.UI.Helpers.TypeMappings.CreateInstance<{namespacePrefix}{subclassName}>())"
: $"new {namespacePrefix}{subclassName}()";
-
+#if USE_NEW_TP_CODEGEN
+ writer.AppendLineIndented($"{activator}.Build(__owner, __settings)");
+#else
writer.AppendLineIndented($"{activator}.Build(__owner)");
+#endif
}
private string GenerateConstructorParameters(INamedTypeSymbol? type)
diff --git a/src/Uno.UI.Maps/MapPresenter.cs b/src/Uno.UI.Maps/MapPresenter.cs
index 2094b25dbeff..9834068782a9 100644
--- a/src/Uno.UI.Maps/MapPresenter.cs
+++ b/src/Uno.UI.Maps/MapPresenter.cs
@@ -25,7 +25,7 @@ private void UpdateOwnerSubscriptions()
{
_ownerSubscription.Disposable = null;
- _owner = TemplatedParent as MapControl;
+ _owner = GetTemplatedParent() as MapControl;
if (_owner != null)
{
diff --git a/src/Uno.UI.RuntimeTests/Helpers/ImageAssert.cs b/src/Uno.UI.RuntimeTests/Helpers/ImageAssert.cs
index c43455d90406..8456d31fc678 100644
--- a/src/Uno.UI.RuntimeTests/Helpers/ImageAssert.cs
+++ b/src/Uno.UI.RuntimeTests/Helpers/ImageAssert.cs
@@ -106,8 +106,9 @@ private static void HasColorAtImpl(RawBitmap screenshot, int x, int y, Color exp
.AppendLine($"Color at ({x},{y}) is not expected")
.AppendLine($"expected: {ToArgbCode(expectedColor)} {expectedColor}")
.AppendLine($"actual : {ToArgbCode(pixel)} {pixel}")
- .AppendLine($"tolerance: {tolerance}")
+ .AppendLine($"tolerance : {tolerance}")
.AppendLine($"difference: {difference}")
+ .AppendLine($"screenshot size: {bitmap.Width}x{bitmap.Height}")
));
}
@@ -173,8 +174,10 @@ public static void HasPixels(RawBitmap actual, params ExpectedPixels[] expectati
var x = expectation.Location.X;
var y = expectation.Location.Y;
- Assert.IsTrue(bitmap.Width >= x);
- Assert.IsTrue(bitmap.Height >= y);
+ Assert.IsTrue(
+ bitmap.Width >= x && bitmap.Height >= y,
+ $"Expectation '{expectation.Name}'@{x},{y} is outside of the provided bitmap ({bitmap.Width}x{bitmap.Height})"
+ );
var result = new StringBuilder();
result.AppendLine(expectation.Name);
diff --git a/src/Uno.UI.RuntimeTests/Helpers/RelativeCoords.cs b/src/Uno.UI.RuntimeTests/Helpers/RelativeCoords.cs
index 1ab564a45900..7fb5a5cb81fe 100644
--- a/src/Uno.UI.RuntimeTests/Helpers/RelativeCoords.cs
+++ b/src/Uno.UI.RuntimeTests/Helpers/RelativeCoords.cs
@@ -1,21 +1,23 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
-using System.Text;
-using Microsoft.UI.Xaml.Media.Imaging;
using System.Runtime.InteropServices.WindowsRuntime;
+using System.Text;
using System.Threading.Tasks;
-using Microsoft.UI.Xaml.Controls;
+using Windows.Foundation;
using Windows.UI;
using Microsoft.UI.Xaml;
-using Windows.Foundation;
+using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
+using Microsoft.UI.Xaml.Media.Imaging;
namespace Uno.UI.RuntimeTests.Helpers
{
///
/// Class that make it possible to find a specific child position in a parent FrameworkElement
///
+ [DebuggerDisplay("{DebugDisplay,nq}")]
public class RelativeCoords// renamed to RelativeCoords
{
private readonly GeneralTransform _transform;
@@ -33,6 +35,8 @@ public static RelativeCoords From(FrameworkElement parent, FrameworkElement chil
return new RelativeCoords(child.TransformToVisual(parent), child.Width, child.Height);
}
+ internal string DebugDisplay => $"{Width:0.#}x{Height:0.#}@{Left:0.#},{Top:0.#}";
+
// note: the transformed (0, 0) position is based the top-left.
public float X => (float)_transform.TransformPoint(new Windows.Foundation.Point(0, 0)).X;
diff --git a/src/Uno.UI.RuntimeTests/Helpers/UITestHelper.cs b/src/Uno.UI.RuntimeTests/Helpers/UITestHelper.cs
index 42ebadf92f8a..c6351e42ba42 100644
--- a/src/Uno.UI.RuntimeTests/Helpers/UITestHelper.cs
+++ b/src/Uno.UI.RuntimeTests/Helpers/UITestHelper.cs
@@ -237,6 +237,18 @@ void DumpState(Point phyLoc)
await popup.ShowAsync(ContentDialogPlacement.Popup);
}
+
+ public static void CloseAllPopups()
+#if HAS_UNO
+ => VisualTreeHelper.CloseAllPopups(TestServices.WindowHelper.XamlRoot);
+#else
+ {
+ foreach (var popup in VisualTreeHelper.GetOpenPopupsForXamlRoot(TestServices.WindowHelper.XamlRoot))
+ {
+ popup.IsOpen = false;
+ }
+ }
+#endif
}
public class DynamicDataTemplate : IDisposable
diff --git a/src/Uno.UI.RuntimeTests/IntegrationTests/dxaml/controls/commandbar/CommandBarIntegrationTests.cs b/src/Uno.UI.RuntimeTests/IntegrationTests/dxaml/controls/commandbar/CommandBarIntegrationTests.cs
index ab3c4001c3e2..03d4891aec76 100644
--- a/src/Uno.UI.RuntimeTests/IntegrationTests/dxaml/controls/commandbar/CommandBarIntegrationTests.cs
+++ b/src/Uno.UI.RuntimeTests/IntegrationTests/dxaml/controls/commandbar/CommandBarIntegrationTests.cs
@@ -304,6 +304,9 @@ public async Task DoesCloseOnSecondaryCommandSelection()
Func openFunc = async (cmdBar) => await RunOnUIThread(() => cmdBar.IsOpen = true);
Func closeFunc = async (cmdBar) =>
{
+ await Task.Delay(2000);
+ await WindowHelper.WaitForIdle();
+
FrameworkElement tapTarget = null;
await RunOnUIThread(() => tapTarget = (FrameworkElement)cmdBar.SecondaryCommands[0]);
@@ -1142,6 +1145,16 @@ await RunOnUIThread(() =>
});
await WindowHelper.WaitForIdle();
+#if true
+ // workaround for initial focus already on MoreButton on certain platforms,
+ // causing the next step unable to re-focus MoreButton again.
+ await RunOnUIThread(() =>
+ {
+ (cmdBar.PrimaryCommands[0] as AppBarButton)?.Focus(FocusState.Programmatic);
+ });
+ await WindowHelper.WaitForIdle();
+#endif
+
focusSequence = "";
// Start focus with more button
diff --git a/src/Uno.UI.RuntimeTests/MUX/Microsoft_UI_Xaml_Controls/TabView/TabViewTests.Uno.cs b/src/Uno.UI.RuntimeTests/MUX/Microsoft_UI_Xaml_Controls/TabView/TabViewTests.Uno.cs
index 11f3650d1aa0..37aac3896ff1 100644
--- a/src/Uno.UI.RuntimeTests/MUX/Microsoft_UI_Xaml_Controls/TabView/TabViewTests.Uno.cs
+++ b/src/Uno.UI.RuntimeTests/MUX/Microsoft_UI_Xaml_Controls/TabView/TabViewTests.Uno.cs
@@ -5,6 +5,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MUXControlsTestApp.Utilities;
using Private.Infrastructure;
+using Uno.UI.RuntimeTests.Helpers;
namespace Microsoft.UI.Xaml.Tests.MUXControls.ApiTests
{
@@ -24,7 +25,7 @@ public async Task VerifyItemsAreCreatedOnlyOnce()
await RunOnUIThread.ExecuteAsync(async () =>
{
tabView = new TabView();
- TestServices.WindowHelper.WindowContent = tabView;
+ await UITestHelper.Load(tabView);
var items = new ObservableCollection()
{
diff --git a/src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Xaml_Controls/Given_NumberBox.cs b/src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Xaml_Controls/Given_NumberBox.cs
index 3bfd02870df8..9a802ddb49e1 100644
--- a/src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Xaml_Controls/Given_NumberBox.cs
+++ b/src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Xaml_Controls/Given_NumberBox.cs
@@ -29,7 +29,7 @@ namespace Uno.UI.RuntimeTests.Tests.Microsoft_UI_Xaml_Controls;
public class Given_NumberBox
{
[TestMethod]
- public async Task When_Fluent_And_Theme_Changed()
+ public async Task When_NB_Fluent_And_Theme_Changed()
{
var textBox = new NumberBox
{
diff --git a/src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Xaml_Controls/Given_TreeView.cs b/src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Xaml_Controls/Given_TreeView.cs
index 3f35f8b3d4cd..3b07fabbe7d5 100644
--- a/src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Xaml_Controls/Given_TreeView.cs
+++ b/src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Xaml_Controls/Given_TreeView.cs
@@ -935,6 +935,16 @@ public async Task When_IsSelectedItem_ParentCollapsed()
Assert.AreEqual(TreeNodeSelectionState.Selected, SUT.NodeFromContainer(SUT.ContainerFromItem(targetItem))?.SelectionState, "[step2]target node is not selected");
#endif
}
+
+ [TestMethod]
+ public async Task When_Simple_ItemsSource()
+ {
+ var SUT = new TreeView()
+ {
+ ItemsSource = new int[] { 1, 2 }
+ };
+ await UITestHelper.Load(SUT);
+ }
}
public partial class Given_TreeView // helper methods, view-models
{
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/BehaviorSetup.xaml b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/BehaviorSetup.xaml
new file mode 100644
index 000000000000..bfe83efffdbf
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/BehaviorSetup.xaml
@@ -0,0 +1,19 @@
+
+
+
+
+
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/BehaviorSetup.xaml.cs b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/BehaviorSetup.xaml.cs
new file mode 100644
index 000000000000..4c515ab34c65
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/BehaviorSetup.xaml.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+#if HAS_UNO
+using Uno.UI.DataBinding;
+#endif
+
+namespace Uno.UI.RuntimeTests.Tests.TemplatedParent.Setup;
+
+public sealed partial class BehaviorSetup : Page
+{
+ public BehaviorSetup()
+ {
+ this.InitializeComponent();
+ }
+}
+
+public sealed class Interaction
+{
+ #region DependencyProperty: Behaviors
+
+ public static DependencyProperty BehaviorsProperty { get; } = DependencyProperty.RegisterAttached(
+ "Behaviors",
+ typeof(BehaviorCollection),
+ typeof(Interaction),
+ new PropertyMetadata(null, OnBehaviorsChanged));
+
+ public static BehaviorCollection GetBehaviors(DependencyObject obj) => GetBehaviorsOverride(obj);
+ public static void SetBehaviors(DependencyObject obj, BehaviorCollection value) => obj.SetValue(BehaviorsProperty, value);
+
+ #endregion
+
+ private static BehaviorCollection GetBehaviorsOverride(DependencyObject obj)
+ {
+ var value = (BehaviorCollection)obj.GetValue(BehaviorsProperty);
+ if (value is null)
+ {
+ obj.SetValue(BehaviorsProperty, value = new BehaviorCollection());
+ }
+
+ return value;
+ }
+
+ private static void OnBehaviorsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
+ {
+ if (e.NewValue is BehaviorCollection collection)
+ {
+ collection.AssociatedObject = sender;
+ }
+ }
+}
+public sealed class BehaviorCollection : DependencyObjectCollection
+{
+ public DependencyObject AssociatedObject { get; set; }
+}
+
+public interface IBehavior { }
+
+public partial class LegacyDOBehavior : DependencyObject, IBehavior
+#if HAS_UNO
+ , INotTemplatedParentProvider
+#endif
+{
+ #region DependencyProperty: TestValue
+
+ public static DependencyProperty TestValueProperty { get; } = DependencyProperty.Register(
+ nameof(TestValue),
+ typeof(object),
+ typeof(LegacyDOBehavior),
+ new PropertyMetadata(default(object), OnTestValueChanged));
+
+ public object TestValue
+ {
+ get => (object)GetValue(TestValueProperty);
+ set => SetValue(TestValueProperty, value);
+ }
+
+ #endregion
+
+ private static void OnTestValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
+ {
+ }
+}
+public partial class NonLegacyDOBehavior : DependencyObject, IBehavior
+{
+ #region DependencyProperty: TestValue
+
+ public static DependencyProperty TestValueProperty { get; } = DependencyProperty.Register(
+ nameof(TestValue),
+ typeof(object),
+ typeof(NonLegacyDOBehavior),
+ new PropertyMetadata(default(object), OnTestValueChanged));
+
+ public object TestValue
+ {
+ get => (object)GetValue(TestValueProperty);
+ set => SetValue(TestValueProperty, value);
+ }
+
+ #endregion
+
+ private static void OnTestValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
+ {
+ }
+}
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ContentControl_Content.xaml b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ContentControl_Content.xaml
new file mode 100644
index 000000000000..cb6df912ef41
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ContentControl_Content.xaml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ContentControl_Content.xaml.cs b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ContentControl_Content.xaml.cs
new file mode 100644
index 000000000000..44d61fc674b7
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ContentControl_Content.xaml.cs
@@ -0,0 +1,11 @@
+using Microsoft.UI.Xaml.Controls;
+
+namespace Uno.UI.RuntimeTests.Tests.TemplatedParent.Setup;
+
+public sealed partial class ContentControl_Content : Page
+{
+ public ContentControl_Content()
+ {
+ this.InitializeComponent();
+ }
+}
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ContentControl_ContentTemplate.xaml b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ContentControl_ContentTemplate.xaml
new file mode 100644
index 000000000000..2a5c029f3d34
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ContentControl_ContentTemplate.xaml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ContentControl_ContentTemplate.xaml.cs b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ContentControl_ContentTemplate.xaml.cs
new file mode 100644
index 000000000000..c925f2422175
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ContentControl_ContentTemplate.xaml.cs
@@ -0,0 +1,11 @@
+using Microsoft.UI.Xaml.Controls;
+
+namespace Uno.UI.RuntimeTests.Tests.TemplatedParent.Setup;
+
+public sealed partial class ContentControl_ContentTemplate : Page
+{
+ public ContentControl_ContentTemplate()
+ {
+ this.InitializeComponent();
+ }
+}
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ItemsControl_HeaderFooter.xaml b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ItemsControl_HeaderFooter.xaml
new file mode 100644
index 000000000000..8b217d5ba4a2
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ItemsControl_HeaderFooter.xaml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ItemsControl_HeaderFooter.xaml.cs b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ItemsControl_HeaderFooter.xaml.cs
new file mode 100644
index 000000000000..07831f47b037
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ItemsControl_HeaderFooter.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Controls.Primitives;
+using Microsoft.UI.Xaml.Data;
+using Microsoft.UI.Xaml.Input;
+using Microsoft.UI.Xaml.Media;
+using Microsoft.UI.Xaml.Navigation;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+
+// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
+
+namespace Uno.UI.RuntimeTests.Tests.TemplatedParent.Setup;
+///
+/// An empty page that can be used on its own or navigated to within a Frame.
+///
+public sealed partial class ItemsControl_HeaderFooter : Page
+{
+ public ItemsControl_HeaderFooter()
+ {
+ this.InitializeComponent();
+ }
+}
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ItemsControl_ItemTemplate.xaml b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ItemsControl_ItemTemplate.xaml
new file mode 100644
index 000000000000..830ca6559677
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ItemsControl_ItemTemplate.xaml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ItemsControl_ItemTemplate.xaml.cs b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ItemsControl_ItemTemplate.xaml.cs
new file mode 100644
index 000000000000..216e1c1bd591
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/ItemsControl_ItemTemplate.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Controls.Primitives;
+using Microsoft.UI.Xaml.Data;
+using Microsoft.UI.Xaml.Input;
+using Microsoft.UI.Xaml.Media;
+using Microsoft.UI.Xaml.Navigation;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+
+// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
+
+namespace Uno.UI.RuntimeTests.Tests.TemplatedParent.Setup;
+///
+/// An empty page that can be used on its own or navigated to within a Frame.
+///
+public sealed partial class ItemsControl_ItemTemplate : Page
+{
+ public ItemsControl_ItemTemplate()
+ {
+ this.InitializeComponent();
+ }
+}
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/TestDP.cs b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/TestDP.cs
new file mode 100644
index 000000000000..a8066f3c04a6
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/TestDP.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.UI.Xaml;
+
+namespace Uno.UI.RuntimeTests.Tests.TemplatedParent.Setup;
+
+public static class TestDP
+{
+ #region DependencyProperty: TestValue
+
+ public static DependencyProperty TestValueProperty { get; } = DependencyProperty.RegisterAttached(
+ "TestValue",
+ typeof(object),
+ typeof(TestDP),
+ new PropertyMetadata(default(object)));
+
+ public static object GetTestValue(DependencyObject obj) => (object)obj.GetValue(TestValueProperty);
+ public static void SetTestValue(DependencyObject obj, object value) => obj.SetValue(TestValueProperty, value);
+
+ #endregion
+}
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno12624.xaml b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno12624.xaml
new file mode 100644
index 000000000000..bb702c71b020
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno12624.xaml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno12624.xaml.cs b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno12624.xaml.cs
new file mode 100644
index 000000000000..bc0d3e6dac5f
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno12624.xaml.cs
@@ -0,0 +1,88 @@
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+
+namespace Uno.UI.RuntimeTests.Tests.TemplatedParent.Setup;
+
+public sealed partial class Uno12624 : Page
+{
+ public Uno12624()
+ {
+ this.InitializeComponent();
+ }
+}
+
+public partial class Uno12624_LeftRightControl : Control
+{
+ #region DependencyProperty: Left
+
+ public static DependencyProperty LeftProperty { get; } = DependencyProperty.Register(
+ nameof(Left),
+ typeof(object),
+ typeof(Uno12624_LeftRightControl),
+ new PropertyMetadata(default(object)));
+
+#if !__ANDROID__
+ public object Left
+#else
+ public new object Left
+#endif
+ {
+ get => (object)GetValue(LeftProperty);
+ set => SetValue(LeftProperty, value);
+ }
+
+ #endregion
+ #region DependencyProperty: Right
+
+ public static DependencyProperty RightProperty { get; } = DependencyProperty.Register(
+ nameof(Right),
+ typeof(object),
+ typeof(Uno12624_LeftRightControl),
+ new PropertyMetadata(default(object)));
+
+#if !__ANDROID__
+ public object Right
+#else
+ public new object Right
+#endif
+ {
+ get => (object)GetValue(RightProperty);
+ set => SetValue(RightProperty, value);
+ }
+
+ #endregion
+}
+
+public partial class Uno12624_WestEastControl : Control
+{
+ #region DependencyProperty: West
+
+ public static DependencyProperty WestProperty { get; } = DependencyProperty.Register(
+ nameof(West),
+ typeof(object),
+ typeof(Uno12624_WestEastControl),
+ new PropertyMetadata(default(object)));
+
+ public object West
+ {
+ get => (object)GetValue(WestProperty);
+ set => SetValue(WestProperty, value);
+ }
+
+ #endregion
+ #region DependencyProperty: East
+
+ public static DependencyProperty EastProperty { get; } = DependencyProperty.Register(
+ nameof(East),
+ typeof(object),
+ typeof(Uno12624_WestEastControl),
+ new PropertyMetadata(default(object)));
+
+ public object East
+ {
+ get => (object)GetValue(EastProperty);
+ set => SetValue(EastProperty, value);
+ }
+
+ #endregion
+}
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno17313.xaml b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno17313.xaml
new file mode 100644
index 000000000000..ecbf865a03f2
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno17313.xaml
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno17313.xaml.cs b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno17313.xaml.cs
new file mode 100644
index 000000000000..b048df3e5020
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno17313.xaml.cs
@@ -0,0 +1,50 @@
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+
+namespace Uno.UI.RuntimeTests.Tests.TemplatedParent.Setup;
+
+public sealed partial class Uno17313 : Page
+{
+ public Uno17313()
+ {
+ this.InitializeComponent();
+ }
+}
+
+public partial class Uno17313_HeaderedCC : ContentControl
+{
+ #region DependencyProperty: Header
+
+ public static DependencyProperty HeaderProperty { get; } = DependencyProperty.Register(
+ nameof(Header),
+ typeof(object),
+ typeof(Uno17313_HeaderedCC),
+ new PropertyMetadata(default(object)));
+
+ public object Header
+ {
+ get => (object)GetValue(HeaderProperty);
+ set => SetValue(HeaderProperty, value);
+ }
+
+ #endregion
+ #region DependencyProperty: HeaderTemplate
+
+ public static DependencyProperty HeaderTemplateProperty { get; } = DependencyProperty.Register(
+ nameof(HeaderTemplate),
+ typeof(DataTemplate),
+ typeof(Uno17313_HeaderedCC),
+ new PropertyMetadata(default(DataTemplate)));
+
+ public DataTemplate HeaderTemplate
+ {
+ get => (DataTemplate)GetValue(HeaderTemplateProperty);
+ set => SetValue(HeaderTemplateProperty, value);
+ }
+
+ #endregion
+}
+
+public partial class Uno17313_Expander : Uno17313_HeaderedCC { }
+public partial class Uno17313_SettingsExpander : Uno17313_HeaderedCC { }
+public partial class Uno17313_SettingsCard : Uno17313_HeaderedCC { }
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno7497.xaml b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno7497.xaml
new file mode 100644
index 000000000000..2e5105d2922e
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno7497.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno7497.xaml.cs b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno7497.xaml.cs
new file mode 100644
index 000000000000..caed4890e773
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno7497.xaml.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Controls.Primitives;
+using Microsoft.UI.Xaml.Data;
+using Microsoft.UI.Xaml.Input;
+using Microsoft.UI.Xaml.Media;
+using Microsoft.UI.Xaml.Navigation;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+
+namespace Uno.UI.RuntimeTests.Tests.TemplatedParent.Setup;
+
+public sealed partial class Uno7497 : Page
+{
+ public Uno7497()
+ {
+ this.InitializeComponent();
+ }
+}
+
+
+public partial class Control7497 : Control
+{
+ #region DependencyProperty: TestList
+
+ public static DependencyProperty TestListProperty { get; } = DependencyProperty.Register(
+ nameof(TestList),
+ typeof(ObservableCollection),
+ typeof(Control7497),
+ new PropertyMetadata(default(ObservableCollection)));
+
+ public ObservableCollection TestList
+ {
+ get => (ObservableCollection)GetValue(TestListProperty);
+ set => SetValue(TestListProperty, value);
+ }
+
+ #endregion
+
+ public Control7497()
+ {
+ DefaultStyleKey = typeof(Control7497);
+ TestList = new ObservableCollection()
+ {
+ "Test 1",
+ "Test 2"
+ };
+ }
+}
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno8049.xaml b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno8049.xaml
new file mode 100644
index 000000000000..acdf043d76af
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno8049.xaml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno8049.xaml.cs b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno8049.xaml.cs
new file mode 100644
index 000000000000..5382456aa02a
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno8049.xaml.cs
@@ -0,0 +1,11 @@
+using Microsoft.UI.Xaml.Controls;
+
+namespace Uno.UI.RuntimeTests.Tests.TemplatedParent.Setup;
+
+public sealed partial class Uno8049 : Page
+{
+ public Uno8049()
+ {
+ this.InitializeComponent();
+ }
+}
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno9059.xaml b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno9059.xaml
new file mode 100644
index 000000000000..6b29e5e43129
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno9059.xaml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno9059.xaml.cs b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno9059.xaml.cs
new file mode 100644
index 000000000000..d763c215c31c
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/Uno9059.xaml.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Windows.Input;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+
+namespace Uno.UI.RuntimeTests.Tests.TemplatedParent.Setup;
+
+public sealed partial class Uno9059 : Page
+{
+ public Uno9059()
+ {
+ this.InitializeComponent();
+ this.DataContext = new Uno9059_VM(() =>
+ {
+ });
+ }
+}
+
+public class Uno9059_VM
+{
+ public Uno9059_VM(Action action)
+ {
+ CustomCommand = new Uno9059_RelayCommand(action);
+ }
+
+ public Uno9059_RelayCommand CustomCommand { get; set; }
+}
+public partial class Uno9059_CustomControl : Control
+{
+ #region DependencyProperty: Action1
+
+ public static DependencyProperty Action1Property { get; } = DependencyProperty.Register(
+ nameof(Action1),
+ typeof(ICommand),
+ typeof(Uno9059_CustomControl),
+ new PropertyMetadata(default(ICommand)));
+
+ public ICommand Action1
+ {
+ get => (ICommand)GetValue(Action1Property);
+ set => SetValue(Action1Property, value);
+ }
+
+ #endregion
+}
+public class Uno9059_RelayCommand : ICommand
+{
+ public event EventHandler CanExecuteChanged;
+ private Action _execute;
+
+ public Uno9059_RelayCommand(Action execute)
+ {
+ _execute = execute;
+
+ CanExecuteChanged?.ToString(); // error CS0067: The event 'Uno9059_RelayCommand.CanExecuteChanged' is never used
+ }
+
+ public bool CanExecute(object parameter) => true;
+
+ public void Execute(object parameter) => _execute?.Invoke();
+}
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/VisualStateGroup_Full.xaml b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/VisualStateGroup_Full.xaml
new file mode 100644
index 000000000000..f8a710454264
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/VisualStateGroup_Full.xaml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/VisualStateGroup_Full.xaml.cs b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/VisualStateGroup_Full.xaml.cs
new file mode 100644
index 000000000000..1572bad9a5e2
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/Setup/VisualStateGroup_Full.xaml.cs
@@ -0,0 +1,11 @@
+using Microsoft.UI.Xaml.Controls;
+
+namespace Uno.UI.RuntimeTests.Tests.TemplatedParent.Setup;
+
+public sealed partial class VisualStateGroup_Full : Page
+{
+ public VisualStateGroup_Full()
+ {
+ this.InitializeComponent();
+ }
+}
diff --git a/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/TemplatedParentTests.cs b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/TemplatedParentTests.cs
new file mode 100644
index 000000000000..2d2b4b02aeaa
--- /dev/null
+++ b/src/Uno.UI.RuntimeTests/Tests/TemplatedParent/TemplatedParentTests.cs
@@ -0,0 +1,464 @@
+#if __ANDROID__ || __IOS__
+// On droid and ios, ContentPresenter bypass can be potentially enabled (based on if a base control template is present, or not).
+// As such, ContentPresenter may be omitted, and altering its descendants templated-parent too.
+#define NEED_CUSTOM_ADJUSTMENTS_FOR_CP_BYPASS
+#endif
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Data;
+using Microsoft.UI.Xaml.Media;
+using Microsoft.UI.Xaml.Media.Animation;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Uno.Extensions;
+using Uno.UI.Extensions;
+using Uno.UI.Helpers;
+using Uno.UI.RuntimeTests.Helpers;
+using Uno.UI.RuntimeTests.Tests.TemplatedParent.Setup;
+#if HAS_UNO
+using Uno.UI.Xaml;
+using Uno.UI.DataBinding;
+#endif
+using WindowHelper = Private.Infrastructure.TestServices.WindowHelper;
+
+namespace Uno.UI.RuntimeTests.Tests.TemplatedParent;
+
+[TestClass]
+[RunsOnUIThread]
+public partial class TemplatedParentTests // tests
+{
+ [TestMethod]
+ public async Task Uno8049_Test()
+ {
+ var setup = new Uno8049();
+ await UITestHelper.Load(setup);
+
+ var tree = setup.TreeGraph(DebugVT_TP);
+ var sut = setup.Content as TextBox ?? throw new Exception("Invalid content root");
+ var cc = sut.FindFirstDescendantOrThrow("HeaderTemplate_ContentControl");
+ var tb = cc.FindFirstDescendantOrThrow("Header_TextBlock");
+
+ Assert.IsNotNull(sut.Header);
+ Assert.AreEqual(sut.Header, tb);
+ }
+
+ [TestMethod]
+ public async Task Uno9059_Test()
+ {
+ try
+ {
+ var setup = new Uno9059();
+ await UITestHelper.Load(setup);
+
+ var sut = setup.Content as Uno9059_CustomControl ?? throw new Exception("Invalid content root");
+ var button = sut.FindFirstDescendantOrThrow