您的位置:首页 > 其它

From Dr.WPF 的Tabcontrol的MVVM性能问题

2010-10-25 21:24 543 查看
http://groups.google.com/group/wpf-disciples/browse_thread/thread/6f3531a1720252dd?pli=1

(moving to public group)

This topic is on my todo list for my ItemsControl series. I just
need to find some blog time.

I have repeatedly brought this issue up with Microsoft (including
last week at the summit). I understand why they chose to implement it
this way, but its not practical for most TabControl scenarios. I want
them to add an option to cache the tab items.

The perf hit is during the building of the tree. Unfortunately, if
you're using a typical MVVM approach with a binding on the ItemsSource
property of the TabControl, the entire tree must be rebuilt each time
a tab item is selected. This is usually a very expensive operation.

To be clear, I don't mind that they unload/reload the items each
time. I just don't want the entire tree discarded. By doing this,
all state associated with the visuals is lost. Maintaining that state
in the VM is usually an unreasonable nightmare.

The discarding of items is really only a problem when using a
TabControl in ItemsSource mode. In Direct mode, the visuals will
still be unloaded from the tree, but they won't be discarded. (See
'C' is for Collection[1] for a description of Direct vs ItemsSource.)

This means you can solve the problem by creating your own TabItem
objects and manually adding them to the TabControl's Items
collection. Yes, this adds a bunch of overhead to the view (which is
why I wish Microsoft would solve the problem in the platform), but if
done right, it still allows an MVVM approach. You just don't get to
use an ItemsSource binding on the TabControl.

Below is what my view code typically looks like for such an approach:

private void OnLoaded(object sender, RoutedEventArgs e)
{
// set initial tabs
foreach (TabViewModel view in TabsCollection)
{
AddTabItem(view);
}

// monitor tabs collection for changes so that tabs can be
updated appropriately
TabsCollection.CollectionChanged += new
NotifyCollectionChangedEventHandler(OnViewsCollectionChanged);

}

private void OnViewsCollectionChanged(object sender,
NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (TabViewModel view in e.NewItems)
{
AddTabItem(view);
}
break;

case NotifyCollectionChangedAction.Remove:
foreach (TabViewModel view in e.OldItems)
{
RemoveTabItem(view);
}
break;

case NotifyCollectionChangedAction.Reset:
_tabControl.Items.Clear();
foreach (TabViewModel view in e.NewItems)
{
AddTabItem(view);
}
break;
}

}

private void AddTabItem(TabViewModel view)
{
TabItem item = new TabItem();
item.DataContext = view;
item.Content = new ContentControl();
(item.Content as ContentControl).Focusable = false;
(item.Content as
ContentControl).SetBinding(ContentControl.ContentProperty, new
Binding());
_tabControl.Items.Add(item);

}

private void RemoveTabItem(TabViewModel view)
{
TabItem foundItem = null;
foreach (TabItem tabItem in _tabControl.Items)
{
if (tabItem.DataContext == view)
{
foundItem = tabItem;
break;
}
}
if (foundItem != null)
{
_tabControl.Items.Remove(foundItem);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: