11// Copyright (c) Microsoft Corporation. All rights reserved.
22// Licensed under the MIT License. See LICENSE in the project root for license information.
33
4+ using System . Collections . Generic ;
45using System . Windows ;
56using System . Windows . Controls ;
67
@@ -24,8 +25,12 @@ public void UserElementFactory(object newValue)
2425 m_itemTemplateWrapper = new ItemTemplateWrapper ( selector ) ;
2526 }
2627 }
28+
29+ navigationViewItemPool = new List < NavigationViewItem > ( ) ;
2730 }
2831
32+ // Retrieve the element that will be displayed for a specific data item.
33+ // If the resolved element is not derived from NavigationViewItemBase, wrap in a NavigationViewItem before returning.
2934 protected override UIElement GetElementCore ( ElementFactoryGetArgs args )
3035 {
3136 object newContent ;
@@ -41,39 +46,106 @@ object init()
4146 newContent = init ( ) ;
4247 }
4348
49+ // Element is already of expected type, just return it
4450 if ( newContent is NavigationViewItemBase newItem )
4551 {
4652 return newItem ;
4753 }
4854
49- // Create a wrapping container for the data
50- var nvi = new NavigationViewItem ( ) ;
51- nvi . Content = newContent ;
52- return nvi ;
53- }
55+ // Get or create a wrapping container for the data
56+ NavigationViewItem nvi ;
57+ {
58+ nvi = init ( ) ;
59+ NavigationViewItem init ( )
60+ {
61+ if ( navigationViewItemPool . Count > 0 )
62+ {
63+ var nvi = navigationViewItemPool . Last ( ) ;
64+ navigationViewItemPool . RemoveLast ( ) ;
65+ return nvi ;
66+ }
67+ return new NavigationViewItem ( ) ;
68+ }
69+ }
70+ var nviImpl = nvi ;
71+ nviImpl . CreatedByNavigationViewItemsFactory = true ;
5472
55- protected override void RecycleElementCore ( ElementFactoryRecycleArgs args )
56- {
73+ // If a user provided item template exists, just pass the template and data down to the ContentPresenter of the NavigationViewItem
5774 if ( m_itemTemplateWrapper != null )
5875 {
59- m_itemTemplateWrapper . RecycleElement ( args ) ;
76+ if ( m_itemTemplateWrapper is ItemTemplateWrapper itemTemplateWrapper )
77+ {
78+ // Recycle newContent
79+ var tempArgs = new ElementFactoryRecycleArgs ( ) ;
80+ tempArgs . Element = newContent as UIElement ;
81+ m_itemTemplateWrapper . RecycleElement ( tempArgs ) ;
82+
83+
84+ nviImpl . Content = args . Data ;
85+ nviImpl . ContentTemplate = itemTemplateWrapper . Template ;
86+ nviImpl . ContentTemplateSelector = itemTemplateWrapper . TemplateSelector ;
87+ return nviImpl ;
88+ }
6089 }
61- else
90+
91+ nviImpl . Content = newContent ;
92+ return nviImpl ;
93+ }
94+
95+ protected override void RecycleElementCore ( ElementFactoryRecycleArgs args )
96+ {
97+ if ( args . Element is { } element )
6298 {
63- // We want to unlink the containers from the parent repeater
64- // in case we are required to move it to a different repeater.
65- if ( args . Parent is Panel panel )
99+ if ( element is NavigationViewItem nvi )
66100 {
67- var children = panel . Children ;
68- int childIndex = 0 ;
69- if ( children . IndexOf ( args . Element , out childIndex ) )
101+ var nviImpl = nvi ;
102+ // Check whether we wrapped the element in a NavigationViewItem ourselves.
103+ // If yes, we are responsible for recycling it.
104+ if ( nviImpl . CreatedByNavigationViewItemsFactory )
70105 {
71- children . RemoveAt ( childIndex ) ;
106+ nviImpl . CreatedByNavigationViewItemsFactory = false ;
107+ UnlinkElementFromParent ( args ) ;
108+ args . Element = null ;
109+
110+ // Retain the NVI that we created for future re-use
111+ navigationViewItemPool . Add ( nvi ) ;
112+
113+ // Retrieve the proper element that requires recycling for a user defined item template
114+ // and update the args correspondingly
115+ if ( m_itemTemplateWrapper != null )
116+ {
117+ // TODO: Retrieve the element and add to the args
118+ }
72119 }
73120 }
121+
122+ if ( m_itemTemplateWrapper != null )
123+ {
124+ m_itemTemplateWrapper . RecycleElement ( args ) ;
125+ }
126+ else
127+ {
128+ UnlinkElementFromParent ( args ) ;
129+ }
130+ }
131+ }
132+
133+ void UnlinkElementFromParent ( ElementFactoryRecycleArgs args )
134+ {
135+ // We want to unlink the containers from the parent repeater
136+ // in case we are required to move it to a different repeater.
137+ if ( args . Parent is Panel panel )
138+ {
139+ var children = panel . Children ;
140+ int childIndex = 0 ;
141+ if ( children . IndexOf ( args . Element , out childIndex ) )
142+ {
143+ children . RemoveAt ( childIndex ) ;
144+ }
74145 }
75146 }
76147
77148 IElementFactoryShim m_itemTemplateWrapper ;
149+ List < NavigationViewItem > navigationViewItemPool = new List < NavigationViewItem > ( ) ;
78150 }
79151}
0 commit comments