mvvm - Encountering lag in WPF Tab Control when switching between tabs (new instance of view is created each time I switch tabs) -
i beginner wpf, , having lot of learning while coding, please bear me. have searched archives, , couldn't find answer fits question.
i have view contains tab control, loaded 2 default tabs, , additional tabs added , removed programmatically based on user actions.
the way having observable collection of viewmodels different types of views can add , remove.
in xaml view, had few different datatemplates used determine kind of view load.
the issue i'm facing when click 1 tab another, seeing lag - close 1 second. put break point in code behind view, , noticed initializecomponent()
method being called view every time click on tab.
the collection of viewmodels called activecontents
, holds items of type activecontent
. activecontent
class 1 created, , contains object named contentitem
hold viewmodel.
here of code project:
one of data templates xaml:
<usercontrol.resources> <resourcedictionary> <resourcedictionary.mergeddictionaries> . . . </resourcedictionary.mergeddictionaries> </resourcedictionary> <datatemplate datatype="{x:type viewmodels:installqueueviewmodel}"> <local:installqueueview datacontext="{binding path=datacontext.installqueuevm, relativesource={relativesource ancestortype={x:type usercontrol}}}" /> </datatemplate> . . . <datatemplate x:key="datatemplatetabcontrolcontent"> <contentcontrol content="{binding contentitem}"></contentcontrol> </datatemplate> </usercontrol.resources> <grid> <tabcontrol itemssource="{binding activecontents}" selectedindex="{binding selectedtab, mode=twoway}" issynchronizedwithcurrentitem="true" itemcontainerstyle="{dynamicresource tabitemcontainerstylespacedmedium}" itemtemplate="{staticresource datatemplatetabcontrolheader}" contenttemplate="{staticresource datatemplatetabcontrolcontent}"> </tabcontrol>
is there way prevent loading new instance of view every time? said, first time, it's entirely possible going wrong way - if should change how i'm doing something, please let me know.
one thing guess should mention i'm using mahapps metro feel application. i'm not sure if contributing @ lag i'm seeing.
i seeing lag when switch view contains datagrid
. considering changing listview
since data read-only, , hoping have give me improvement, root cause still unresolved.
any appreciated.
this huge problem me 1 project, , ended creating extended tabcontrol
save contentpresenter
of each tabitem
when switching tabs, , reloading when go tab.
the original version of code here, or can find version of code in related question problem while back: wpf tabcontrol - preventing unload on tab change?
// extended tabcontrol saves displayed item don't performance hit of // unloading , reloading visualtree when switching tabs // obtained http://eric.burke.name/dotnetmania/2009/04/26/22.09.28 // , made modifications reuses tabitem's contentpresenter when doing drag/drop operations [templatepart(name = "part_itemsholder", type = typeof(panel))] public class tabcontrolex : system.windows.controls.tabcontrol { // holds items, marks current tab's item visible private panel _itemsholder = null; // temporaily holds deleted item in case drag/drop operation private object _deletedobject = null; public tabcontrolex() : base() { // necessary initial databound selected item this.itemcontainergenerator.statuschanged += itemcontainergenerator_statuschanged; } /// <summary> /// if containers done, generate selected item /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void itemcontainergenerator_statuschanged(object sender, eventargs e) { if (this.itemcontainergenerator.status == generatorstatus.containersgenerated) { this.itemcontainergenerator.statuschanged -= itemcontainergenerator_statuschanged; updateselecteditem(); } } /// <summary> /// itemsholder , generate children /// </summary> public override void onapplytemplate() { base.onapplytemplate(); _itemsholder = gettemplatechild("part_itemsholder") panel; updateselecteditem(); } /// <summary> /// when items change remove generated panel children , add new ones necessary /// </summary> /// <param name="e"></param> protected override void onitemschanged(notifycollectionchangedeventargs e) { base.onitemschanged(e); if (_itemsholder == null) { return; } switch (e.action) { case notifycollectionchangedaction.reset: _itemsholder.children.clear(); if (base.items.count > 0) { base.selecteditem = base.items[0]; updateselecteditem(); } break; case notifycollectionchangedaction.add: case notifycollectionchangedaction.remove: // search deleted items caused drag/drop operation if (e.newitems != null && _deletedobject != null) { foreach (var item in e.newitems) { if (_deletedobject == item) { // if new item same deleted 1 (i.e. drag/drop event) // cancel deletion , reuse contentpresenter doesn't have // redrawn. need link presenter new item though (using tag) contentpresenter cp = findchildcontentpresenter(_deletedobject); if (cp != null) { int index = _itemsholder.children.indexof(cp); (_itemsholder.children[index] contentpresenter).tag = (item tabitem) ? item : (this.itemcontainergenerator.containerfromitem(item)); } _deletedobject = null; } } } if (e.olditems != null) { foreach (var item in e.olditems) { _deletedobject = item; // want run @ later priority in case // drag/drop operation can reuse template this.dispatcher.begininvoke(dispatcherpriority.databind, new action(delegate() { if (_deletedobject != null) { contentpresenter cp = findchildcontentpresenter(_deletedobject); if (cp != null) { this._itemsholder.children.remove(cp); } } } )); } } updateselecteditem(); break; case notifycollectionchangedaction.replace: throw new notimplementedexception("replace not implemented yet"); } } /// <summary> /// update visible child in itemsholder /// </summary> /// <param name="e"></param> protected override void onselectionchanged(selectionchangedeventargs e) { base.onselectionchanged(e); updateselecteditem(); } /// <summary> /// generate contentpresenter selected item /// </summary> void updateselecteditem() { if (_itemsholder == null) { return; } // generate contentpresenter if necessary tabitem item = getselectedtabitem(); if (item != null) { createchildcontentpresenter(item); } // show right child foreach (contentpresenter child in _itemsholder.children) { child.visibility = ((child.tag tabitem).isselected) ? visibility.visible : visibility.collapsed; } } /// <summary> /// create child contentpresenter given item (could data or tabitem) /// </summary> /// <param name="item"></param> /// <returns></returns> contentpresenter createchildcontentpresenter(object item) { if (item == null) { return null; } contentpresenter cp = findchildcontentpresenter(item); if (cp != null) { return cp; } // actual child added. cp.tag reference tabitem cp = new contentpresenter(); cp.content = (item tabitem) ? (item tabitem).content : item; cp.contenttemplate = this.selectedcontenttemplate; cp.contenttemplateselector = this.selectedcontenttemplateselector; cp.contentstringformat = this.selectedcontentstringformat; cp.visibility = visibility.collapsed; cp.tag = (item tabitem) ? item : (this.itemcontainergenerator.containerfromitem(item)); _itemsholder.children.add(cp); return cp; } /// <summary> /// find cp given object. data tabitem or piece of data /// </summary> /// <param name="data"></param> /// <returns></returns> contentpresenter findchildcontentpresenter(object data) { if (data tabitem) { data = (data tabitem).content; } if (data == null) { return null; } if (_itemsholder == null) { return null; } foreach (contentpresenter cp in _itemsholder.children) { if (cp.content == data) { return cp; } } return null; } /// <summary> /// copied tabcontrol; wish protected in class instead of private /// </summary> /// <returns></returns> protected tabitem getselectedtabitem() { object selecteditem = base.selecteditem; if (selecteditem == null) { return null; } if (_deletedobject == selecteditem) { } tabitem item = selecteditem tabitem; if (item == null) { item = base.itemcontainergenerator.containerfromindex(base.selectedindex) tabitem; } return item; } }
Comments
Post a Comment