From ea44d536271ca0df44082bdc999f5d151eea198d Mon Sep 17 00:00:00 2001 From: Ramez Ragaa Date: Tue, 27 Feb 2024 20:18:50 +0200 Subject: [PATCH] fix: DeferLoadStrategy should work even if no visibility is set --- .../XamlGenerator/XamlFileGenerator.cs | 263 +++++++++--------- 1 file changed, 130 insertions(+), 133 deletions(-) diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs index 3eb5ea1d0f2c..ec32dfe00d4b 100644 --- a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs +++ b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs @@ -6319,199 +6319,196 @@ private IEnumerable EnumerateSubElements(IEnumerable "); - var currentOwnerName = CurrentResourceOwnerName; + var disposable = new DisposableAction(() => + { + writer.AppendIndented(")"); + }); + + var xLoadScopeDisposable = XLoadScope(); - var elementStubHolderNameStatement = ""; + return new DisposableAction(() => + { + disposable?.Dispose(); - if (HasImplicitViewPinning) + string closureName; + using (var innerWriter = CreateApplyBlock(writer, Generation.ElementStubSymbol.Value, out closureName)) { - // Build the ElemenStub builder holder variable to ensute that the element stub - // does not keep a hard reference to "this" through the closure needed to keep - // the namescope and other variables. The ElementStub, in turn keeps a weak - // reference to the builder's target instance. - var elementStubHolderName = $"_elementStubHolder_{CurrentScope.ElementStubHolders.Count}"; - elementStubHolderNameStatement = $"{elementStubHolderName} = "; - CurrentScope.ElementStubHolders.Add(elementStubHolderName); - } + var elementStubType = new XamlType(XamlConstants.BaseXamlNamespace, "ElementStub", new List(), new XamlSchemaContext()); - writer.AppendLineIndented($"new {XamlConstants.Types.ElementStub}({elementStubHolderNameStatement} () => "); + if (hasDataContextMarkup) + { + // We need to generate the datacontext binding, since the Visibility + // may require it to bind properly. - var disposable = new DisposableAction(() => - { - writer.AppendIndented(")"); - }); + GenerateBinding("DataContext", dataContextMember, definition); + } - var xLoadScopeDisposable = XLoadScope(); + if (nameMember != null) + { + innerWriter.AppendLineIndented( + $"{closureName}.Name = \"{nameMember.Value}\";" + ); - return new DisposableAction(() => - { - disposable?.Dispose(); + // Set the element name to the stub, then when the stub will be replaced + // the actual target control will override it. + innerWriter.AppendLineIndented( + $"_{nameMember.Value}Subject.ElementInstance = {closureName};" + ); + } - string closureName; - using (var innerWriter = CreateApplyBlock(writer, Generation.ElementStubSymbol.Value, out closureName)) + if (hasLoadMarkup || hasVisibilityMarkup) { - var elementStubType = new XamlType(XamlConstants.BaseXamlNamespace, "ElementStub", new List(), new XamlSchemaContext()); - if (hasDataContextMarkup) - { - // We need to generate the datacontext binding, since the Visibility - // may require it to bind properly. + var members = new List(); - GenerateBinding("DataContext", dataContextMember, definition); + if (hasLoadMarkup) + { + members.Add(GenerateBinding("Load", loadMember, definition)); } - if (nameMember != null) + if (hasVisibilityMarkup) { - innerWriter.AppendLineIndented( - $"{closureName}.Name = \"{nameMember.Value}\";" - ); - - // Set the element name to the stub, then when the stub will be replaced - // the actual target control will override it. - innerWriter.AppendLineIndented( - $"_{nameMember.Value}Subject.ElementInstance = {closureName};" - ); + members.Add(GenerateBinding("Visibility", visibilityMember, definition)); } - if (hasLoadMarkup || hasVisibilityMarkup) + var isInsideFrameworkTemplate = IsMemberInsideFrameworkTemplate(definition).isInside; + if ((!_isTopLevelDictionary || isInsideFrameworkTemplate) + && (HasXBindMarkupExtension(definition) || HasMarkupExtensionNeedingComponent(definition))) { + var xamlObjectDef = new XamlObjectDefinition(elementStubType, 0, 0, definition, namespaces: null); + xamlObjectDef.Members.AddRange(members); - var members = new List(); - - if (hasLoadMarkup) - { - members.Add(GenerateBinding("Load", loadMember, definition)); - } + AddComponentForParentScope(xamlObjectDef); - if (hasVisibilityMarkup) - { - members.Add(GenerateBinding("Visibility", visibilityMember, definition)); - } + var componentName = CurrentScope.Components.Last().MemberName; + writer.AppendLineIndented($"__that.{componentName} = {closureName};"); - var isInsideFrameworkTemplate = IsMemberInsideFrameworkTemplate(definition).isInside; - if ((!_isTopLevelDictionary || isInsideFrameworkTemplate) - && (HasXBindMarkupExtension(definition) || HasMarkupExtensionNeedingComponent(definition))) + if (!isInsideFrameworkTemplate) { - var xamlObjectDef = new XamlObjectDefinition(elementStubType, 0, 0, definition, namespaces: null); - xamlObjectDef.Members.AddRange(members); + EnsureXClassName(); - AddComponentForParentScope(xamlObjectDef); + writer.AppendLineIndented($"var {componentName}_update_That = ({CurrentResourceOwnerName} as global::Uno.UI.DataBinding.IWeakReferenceProvider).WeakReference;"); - var componentName = CurrentScope.Components.Last().MemberName; - writer.AppendLineIndented($"__that.{componentName} = {closureName};"); - - if (!isInsideFrameworkTemplate) + if (nameMember != null) { - EnsureXClassName(); - - writer.AppendLineIndented($"var {componentName}_update_That = ({CurrentResourceOwnerName} as global::Uno.UI.DataBinding.IWeakReferenceProvider).WeakReference;"); + writer.AppendLineIndented($"var {componentName}_update_subject_capture = _{nameMember.Value}Subject;"); + } - if (nameMember != null) + using (writer.BlockInvariant($"void {componentName}_update(global::Microsoft.UI.Xaml.ElementStub sender)")) + { + using (writer.BlockInvariant($"if ({componentName}_update_That.Target is {_xClassName} that)")) { - writer.AppendLineIndented($"var {componentName}_update_subject_capture = _{nameMember.Value}Subject;"); - } - using (writer.BlockInvariant($"void {componentName}_update(global::Microsoft.UI.Xaml.ElementStub sender)")) - { - using (writer.BlockInvariant($"if ({componentName}_update_That.Target is {_xClassName} that)")) + using (writer.BlockInvariant($"if (sender.IsMaterialized)")) { - - using (writer.BlockInvariant($"if (sender.IsMaterialized)")) - { - writer.AppendLineIndented($"that.Bindings.UpdateResources();"); - } + writer.AppendLineIndented($"that.Bindings.UpdateResources();"); } } + } - writer.AppendLineIndented($"{closureName}.MaterializationChanged += {componentName}_update;"); + writer.AppendLineIndented($"{closureName}.MaterializationChanged += {componentName}_update;"); - writer.AppendLineIndented($"var owner = this;"); + writer.AppendLineIndented($"var owner = this;"); + + if (_isHotReloadEnabled) + { + // Attach the current context to itself to avoid having a closure in the lambda + writer.AppendLineIndented($"global::Uno.UI.Helpers.MarkupHelper.SetElementProperty({closureName}, \"{componentName}_owner\", owner);"); + } + using (writer.BlockInvariant($"void {componentName}_materializing(object sender)")) + { if (_isHotReloadEnabled) { - // Attach the current context to itself to avoid having a closure in the lambda - writer.AppendLineIndented($"global::Uno.UI.Helpers.MarkupHelper.SetElementProperty({closureName}, \"{componentName}_owner\", owner);"); + writer.AppendLineIndented($"var owner = global::Uno.UI.Helpers.MarkupHelper.GetElementProperty<{CurrentScope.ClassName}>(sender, \"{componentName}_owner\");"); } - using (writer.BlockInvariant($"void {componentName}_materializing(object sender)")) - { - if (_isHotReloadEnabled) - { - writer.AppendLineIndented($"var owner = global::Uno.UI.Helpers.MarkupHelper.GetElementProperty<{CurrentScope.ClassName}>(sender, \"{componentName}_owner\");"); - } - - // Refresh the bindings when the ElementStub is unloaded. This assumes that - // ElementStub will be unloaded **after** the stubbed control has been created - // in order for the component field to be filled, and Bindings.Update() to do its work. + // Refresh the bindings when the ElementStub is unloaded. This assumes that + // ElementStub will be unloaded **after** the stubbed control has been created + // in order for the component field to be filled, and Bindings.Update() to do its work. - using (writer.BlockInvariant($"if ({componentName}_update_That.Target is {_xClassName} that)")) + using (writer.BlockInvariant($"if ({componentName}_update_That.Target is {_xClassName} that)")) + { + if (CurrentXLoadScope != null) { - if (CurrentXLoadScope != null) + foreach (var component in CurrentXLoadScope.Components) { - foreach (var component in CurrentXLoadScope.Components) - { - writer.AppendLineIndented($"that.{component.VariableName}.ApplyXBind();"); - writer.AppendLineIndented($"that.{component.VariableName}.UpdateResourceBindings();"); - } - - BuildxBindEventHandlerInitializers(writer, CurrentXLoadScope.xBindEventsHandlers, "that."); + writer.AppendLineIndented($"that.{component.VariableName}.ApplyXBind();"); + writer.AppendLineIndented($"that.{component.VariableName}.UpdateResourceBindings();"); } + + BuildxBindEventHandlerInitializers(writer, CurrentXLoadScope.xBindEventsHandlers, "that."); } } - - writer.AppendLineIndented($"{closureName}.Materializing += {componentName}_materializing;"); - } - else - { - // TODO for https://github.com/unoplatform/uno/issues/6700 } + writer.AppendLineIndented($"{closureName}.Materializing += {componentName}_materializing;"); } - } - else - { - if (visibilityMember != null) + else { - innerWriter.AppendLineInvariantIndented( - "{0}.Visibility = {1};", - closureName, - BuildLiteralValue(visibilityMember) - ); + // TODO for https://github.com/unoplatform/uno/issues/6700 } - } - XamlMemberDefinition GenerateBinding(string name, XamlMemberDefinition? memberDefinition, XamlObjectDefinition owner) + } + } + else + { + if (visibilityMember != null) { - var def = new XamlMemberDefinition( - new XamlMember(name, - elementStubType, - false - ), 0, 0, - owner + innerWriter.AppendLineInvariantIndented( + "{0}.Visibility = {1};", + closureName, + BuildLiteralValue(visibilityMember) ); + } + } - if (memberDefinition != null) - { - def.Objects.AddRange(memberDefinition.Objects); - } - - BuildComplexPropertyValue(innerWriter, def, closureName + ".", closureName); + XamlMemberDefinition GenerateBinding(string name, XamlMemberDefinition? memberDefinition, XamlObjectDefinition owner) + { + var def = new XamlMemberDefinition( + new XamlMember(name, + elementStubType, + false + ), 0, 0, + owner + ); - return def; + if (memberDefinition != null) + { + def.Objects.AddRange(memberDefinition.Objects); } - } - xLoadScopeDisposable?.Dispose(); + BuildComplexPropertyValue(innerWriter, def, closureName + ".", closureName); + + return def; + } } - ); + + xLoadScopeDisposable?.Dispose(); } + ); } return null;