@@ -56,6 +56,7 @@ internal partial class XamlFileGenerator
56
56
/// </summary>
57
57
private readonly Dictionary < ( string ? Theme , string ResourceKey ) , string > _topLevelQualifiedKeys = new Dictionary < ( string ? , string ) , string > ( ) ;
58
58
private readonly Stack < NameScope > _scopeStack = new Stack < NameScope > ( ) ;
59
+ private readonly Stack < XLoadScope > _xLoadScopeStack = new Stack < XLoadScope > ( ) ;
59
60
private readonly Stack < ResourceOwner > _resourceOwnerStack = new Stack < ResourceOwner > ( ) ;
60
61
private readonly XamlFileDefinition _fileDefinition ;
61
62
private readonly string _targetPath ;
@@ -835,7 +836,7 @@ private void BuildCompiledBindingsInitializer(IndentedStringBuilder writer, stri
835
836
{
836
837
TryAnnotateWithGeneratorSource ( writer ) ;
837
838
var hasXBindExpressions = CurrentScope . XBindExpressions . Count != 0 ;
838
- var hasResourceExtensions = CurrentScope . Components . Any ( HasMarkupExtensionNeedingComponent ) ;
839
+ var hasResourceExtensions = CurrentScope . Components . Any ( c => HasMarkupExtensionNeedingComponent ( c . XamlObject ) ) ;
839
840
var isFrameworkElement =
840
841
IsType ( className , _frameworkElementSymbol ) // The current type may not have a base type as it is defined in XAML,
841
842
|| IsType ( controlBaseType , _frameworkElementSymbol ) ; // so look at the control base type extracted from the XAML.
@@ -864,7 +865,7 @@ private void BuildCompiledBindingsInitializer(IndentedStringBuilder writer, stri
864
865
private void BuildCompiledBindingsInitializerForTemplate ( IIndentedStringBuilder writer )
865
866
{
866
867
TryAnnotateWithGeneratorSource ( writer ) ;
867
- var hasResourceExtensions = CurrentScope . Components . Any ( HasMarkupExtensionNeedingComponent ) ;
868
+ var hasResourceExtensions = CurrentScope . Components . Any ( c => HasMarkupExtensionNeedingComponent ( c . XamlObject ) ) ;
868
869
869
870
if ( hasResourceExtensions )
870
871
{
@@ -873,16 +874,16 @@ private void BuildCompiledBindingsInitializerForTemplate(IIndentedStringBuilder
873
874
using ( writer . BlockInvariant ( $ "__fe.Loading += delegate") )
874
875
{
875
876
BuildComponentResouceBindingUpdates ( writer ) ;
876
- BuildxBindEventHandlerInitializers ( writer ) ;
877
+ BuildxBindEventHandlerInitializers ( writer , CurrentScope . xBindEventsHandlers ) ;
877
878
}
878
879
writer . AppendLineInvariant ( ";" ) ;
879
880
}
880
881
}
881
882
}
882
883
883
- private void BuildxBindEventHandlerInitializers ( IIndentedStringBuilder writer , string prefix = "" )
884
+ private static void BuildxBindEventHandlerInitializers ( IIndentedStringBuilder writer , List < BackingFieldDefinition > xBindEventsHandlers , string prefix = "" )
884
885
{
885
- foreach ( var xBindEventHandler in CurrentScope . xBindEventsHandlers )
886
+ foreach ( var xBindEventHandler in xBindEventsHandlers )
886
887
{
887
888
writer . AppendLineInvariant ( $ "{ prefix } { xBindEventHandler . Name } ?.Invoke();") ;
888
889
@@ -897,7 +898,7 @@ private void BuildComponentResouceBindingUpdates(IIndentedStringBuilder writer)
897
898
{
898
899
var component = CurrentScope . Components [ i ] ;
899
900
900
- if ( HasMarkupExtensionNeedingComponent ( component ) && IsDependencyObject ( component ) )
901
+ if ( HasMarkupExtensionNeedingComponent ( component . XamlObject ) && IsDependencyObject ( component . XamlObject ) )
901
902
{
902
903
writer . AppendLineInvariant ( $ "_component_{ i } .UpdateResourceBindings();") ;
903
904
}
@@ -911,11 +912,12 @@ private void BuildComponentFields(IIndentedStringBuilder writer)
911
912
var current = CurrentScope . Components [ i ] ;
912
913
913
914
var componentName = $ "_component_{ i } ";
914
- var typeName = GetType ( current . Type ) . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) ;
915
+ var typeName = GetType ( current . XamlObject . Type ) . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) ;
915
916
916
- writer . AppendLineInvariant ( $ "private global::Windows.UI.Xaml.Markup.ComponentHolder { componentName } _Holder = new global::Windows.UI.Xaml.Markup.ComponentHolder();") ;
917
+ var isWeak = current . IsWeakReference ? "true" : "false" ;
918
+ writer . AppendLineInvariant ( $ "private global::Windows.UI.Xaml.Markup.ComponentHolder { componentName } _Holder = new global::Windows.UI.Xaml.Markup.ComponentHolder(isWeak: { isWeak } );") ;
917
919
918
- using ( writer . BlockInvariant ( $ "private { GetType ( current . Type ) . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) } _component_{ i } ") )
920
+ using ( writer . BlockInvariant ( $ "private { GetType ( current . XamlObject . Type ) . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) } _component_{ i } ") )
919
921
{
920
922
using ( writer . BlockInvariant ( "get" ) )
921
923
{
@@ -933,7 +935,7 @@ private void BuildComponentFields(IIndentedStringBuilder writer)
933
935
private void BuildCompiledBindings ( IndentedStringBuilder writer , string className )
934
936
{
935
937
var hasXBindExpressions = CurrentScope . XBindExpressions . Count != 0 ;
936
- var hasResourceExtensions = CurrentScope . Components . Any ( HasMarkupExtensionNeedingComponent ) ;
938
+ var hasResourceExtensions = CurrentScope . Components . Any ( c => HasMarkupExtensionNeedingComponent ( c . XamlObject ) ) ;
937
939
938
940
if ( hasXBindExpressions || hasResourceExtensions )
939
941
{
@@ -975,16 +977,16 @@ private void BuildCompiledBindings(IndentedStringBuilder writer, string classNam
975
977
{
976
978
var component = CurrentScope . Components [ i ] ;
977
979
978
- if ( HasXBindMarkupExtension ( component ) )
980
+ if ( HasXBindMarkupExtension ( component . XamlObject ) )
979
981
{
980
- var isDependencyObject = IsDependencyObject ( component ) ;
982
+ var isDependencyObject = IsDependencyObject ( component . XamlObject ) ;
981
983
982
984
var wrapInstance = isDependencyObject ? "" : ".GetDependencyObjectForXBind()" ;
983
985
984
986
writer . AppendLineInvariant ( $ "owner._component_{ i } { wrapInstance } .ApplyXBind();") ;
985
987
}
986
988
987
- BuildxBindEventHandlerInitializers ( writer , "owner." ) ;
989
+ BuildxBindEventHandlerInitializers ( writer , CurrentScope . xBindEventsHandlers , "owner." ) ;
988
990
}
989
991
}
990
992
using ( writer . BlockInvariant ( $ "void { bindingsInterfaceName } .UpdateResources()") )
@@ -995,7 +997,7 @@ private void BuildCompiledBindings(IndentedStringBuilder writer, string classNam
995
997
{
996
998
var component = CurrentScope . Components [ i ] ;
997
999
998
- if ( HasMarkupExtensionNeedingComponent ( component ) && IsDependencyObject ( component ) )
1000
+ if ( HasMarkupExtensionNeedingComponent ( component . XamlObject ) && IsDependencyObject ( component . XamlObject ) )
999
1001
{
1000
1002
writer . AppendLineInvariant ( $ "owner._component_{ i } .UpdateResourceBindings();") ;
1001
1003
}
@@ -3282,7 +3284,7 @@ private void BuildExtendedProperties(IIndentedStringBuilder outerwriter, XamlObj
3282
3284
writer . AppendLineInvariant ( $ "global::Windows.UI.Xaml.NameScope.SetNameScope(this._component_{ CurrentScope . ComponentCount } , nameScope);") ;
3283
3285
}
3284
3286
3285
- CurrentScope . Components . Add ( objectDefinition ) ;
3287
+ AddComponentForCurrentScope ( objectDefinition ) ;
3286
3288
}
3287
3289
else if ( isFrameworkElement && HasMarkupExtensionNeedingComponent ( objectDefinition ) )
3288
3290
{
@@ -3469,9 +3471,7 @@ IMethodSymbol FindTargetMethodSymbol(INamedTypeSymbol? sourceType)
3469
3471
3470
3472
var builderName = $ "_{ ownerPrefix } _{ CurrentScope . xBindEventsHandlers . Count } _{ member . Member . Name } _{ sanitizedEventTarget } _Builder";
3471
3473
3472
- CurrentScope . xBindEventsHandlers . Add (
3473
- new BackingFieldDefinition ( "global::System.Action" , builderName , Accessibility . Private )
3474
- ) ;
3474
+ AddXBindEventHandlerToScope ( builderName ) ;
3475
3475
3476
3476
using ( writer . BlockInvariant ( $ "{ builderName } = () => ") )
3477
3477
{
@@ -5536,6 +5536,8 @@ private IEnumerable<XamlObjectDefinition> EnumerateSubElements(IEnumerable<XamlO
5536
5536
writer . AppendLine ( ")" ) ;
5537
5537
} ) ;
5538
5538
5539
+ var xLoadScopeDisposable = XLoadScope ( ) ;
5540
+
5539
5541
return new DisposableAction ( ( ) =>
5540
5542
{
5541
5543
disposable ? . Dispose ( ) ;
@@ -5615,7 +5617,20 @@ private IEnumerable<XamlObjectDefinition> EnumerateSubElements(IEnumerable<XamlO
5615
5617
// Refresh the bindings when the ElementStub is unloaded. This assumes that
5616
5618
// ElementStub will be unloaded **after** the stubbed control has been created
5617
5619
// in order for the _component_XXX to be filled, and Bindings.Update() to do its work.
5618
- writer . AppendLineInvariant ( $ "({ componentName } _update_That.Target as { _className . className } )?.Bindings.Update();") ;
5620
+
5621
+ using ( writer . BlockInvariant ( $ "if ({ componentName } _update_That.Target is { _className . className } that)") )
5622
+ {
5623
+ if ( CurrentXLoadScope != null )
5624
+ {
5625
+ foreach ( var component in CurrentXLoadScope . Components )
5626
+ {
5627
+ writer . AppendLineInvariant ( $ "that.{ component . VariableName } .ApplyXBind();") ;
5628
+ writer . AppendLineInvariant ( $ "that.{ component . VariableName } .UpdateResourceBindings();") ;
5629
+ }
5630
+
5631
+ BuildxBindEventHandlerInitializers ( writer , CurrentXLoadScope . xBindEventsHandlers , "that." ) ;
5632
+ }
5633
+ }
5619
5634
}
5620
5635
5621
5636
writer . AppendLineInvariant ( $ "{ closureName } .Materializing += { componentName } _materializing;") ;
@@ -5627,9 +5642,11 @@ private IEnumerable<XamlObjectDefinition> EnumerateSubElements(IEnumerable<XamlO
5627
5642
5628
5643
var xamlObjectDef = new XamlObjectDefinition ( elementStubType , 0 , 0 , definition ) ;
5629
5644
xamlObjectDef . Members . AddRange ( members ) ;
5630
- CurrentScope . Components . Add ( xamlObjectDef ) ;
5631
- }
5632
5645
5646
+ // Add the element stub as a strong reference, so that the
5647
+ // stub can be brought back if the loaded state changes.
5648
+ AddComponentForParentScope ( xamlObjectDef , isWeak : false ) ;
5649
+ }
5633
5650
}
5634
5651
else
5635
5652
{
@@ -5663,6 +5680,8 @@ XamlMemberDefinition GenerateBinding(string name, XamlMemberDefinition? memberDe
5663
5680
return def ;
5664
5681
}
5665
5682
}
5683
+
5684
+ xLoadScopeDisposable ? . Dispose ( ) ;
5666
5685
}
5667
5686
) ;
5668
5687
}
@@ -5910,18 +5929,56 @@ private bool IsDirectUserControlSubType(XamlObjectDefinition objectDefinition)
5910
5929
}
5911
5930
5912
5931
private NameScope CurrentScope
5932
+ => _scopeStack . Peek ( ) ;
5933
+
5934
+ private IDisposable Scope ( string ? @namespace , string className )
5913
5935
{
5914
- get
5936
+ _scopeStack . Push ( new NameScope ( @namespace , className ) ) ;
5937
+
5938
+ return new DisposableAction ( ( ) => _scopeStack . Pop ( ) ) ;
5939
+ }
5940
+
5941
+ private void AddComponentForCurrentScope ( XamlObjectDefinition objectDefinition )
5942
+ {
5943
+ CurrentScope . Components . Add ( new ComponentDefinition ( objectDefinition , true ) ) ;
5944
+
5945
+ if ( CurrentXLoadScope is { } xLoadScope )
5915
5946
{
5916
- return _scopeStack . Peek ( ) ;
5947
+ CurrentXLoadScope . Components . Add ( new ComponentEntry ( $ "_component_ { CurrentScope . ComponentCount - 1 } " , objectDefinition ) ) ;
5917
5948
}
5918
5949
}
5919
5950
5920
- private IDisposable Scope ( string ? @namespace , string className )
5951
+ private void AddComponentForParentScope ( XamlObjectDefinition objectDefinition , bool isWeak )
5921
5952
{
5922
- _scopeStack . Push ( new NameScope ( @namespace , className ) ) ;
5953
+ CurrentScope . Components . Add ( new ComponentDefinition ( objectDefinition , isWeak ) ) ;
5923
5954
5924
- return new DisposableAction ( ( ) => _scopeStack . Pop ( ) ) ;
5955
+ if ( _xLoadScopeStack . Count > 1 )
5956
+ {
5957
+ var parent = _xLoadScopeStack . Skip ( 1 ) . First ( ) ;
5958
+
5959
+ parent . Components . Add ( new ComponentEntry ( $ "_component_{ CurrentScope . ComponentCount - 1 } ", objectDefinition ) ) ;
5960
+ }
5961
+ }
5962
+ private void AddXBindEventHandlerToScope ( string fieldName )
5963
+ {
5964
+ var definition = new BackingFieldDefinition ( "global::System.Action" , fieldName , Accessibility . Private ) ;
5965
+
5966
+ CurrentScope . xBindEventsHandlers . Add ( definition ) ;
5967
+
5968
+ if ( CurrentXLoadScope is { } xLoadScope )
5969
+ {
5970
+ CurrentXLoadScope . xBindEventsHandlers . Add ( definition ) ;
5971
+ }
5972
+ }
5973
+
5974
+ private XLoadScope ? CurrentXLoadScope
5975
+ => _xLoadScopeStack . Count != 0 ? _xLoadScopeStack . Peek ( ) : null ;
5976
+
5977
+ private IDisposable XLoadScope ( )
5978
+ {
5979
+ _xLoadScopeStack . Push ( new XLoadScope ( ) ) ;
5980
+
5981
+ return new DisposableAction ( ( ) => _xLoadScopeStack . Pop ( ) ) ;
5925
5982
}
5926
5983
5927
5984
private ResourceOwner ? CurrentResourceOwner
0 commit comments