2010-02-10 55 views
3

我正在为我的应用程序使用MVVM模式。的主窗口包括与映射到视图模型的一个DataContextTabControlTabControl处理非活动选项卡上的控件

<Window.Resources> 
    <ResourceDictionary> 
    <DataTemplate x:Key="templateMainTabControl"> 
     <ContentPresenter Content="{Binding Path=DisplayName}" /> 
    </DataTemplate> 

    <local:ViewModel x:Key="VM" /> 
    <local:WorkspaceSelector x:Key="WorkspaceSelector" /> 
    <local:TabOneView x:Key="TabOneView" /> 
    <local:TabTableView x:Key="TabTableView" /> 

    <DataTemplate x:Key="TabOne"> 
     <local:TabOneView /> 
    </DataTemplate> 

    <DataTemplate x:Key="TabTable"> 
     <local:TabTableView /> 
    </DataTemplate> 

    </ResourceDictionary> 
</Window.Resources> 


<TabControl Grid.Row="0" 
      DataContext="{StaticResource VM}" 
      ItemsSource="{Binding Workspaces}" 
      SelectedItem="{Binding SelectedWorkspace}" 
      ItemTemplate="{StaticResource templateMainTabControl}" 
      ContentTemplateSelector="{StaticResource WorkspaceSelector}" /> 

WorkspaceSelector看起来像:

public class WorkspaceSelector : DataTemplateSelector 
{ 
    public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    { 
    Window win = Application.Current.MainWindow; 
    Workspace w = (Workspace) item; 
    string key = w.DisplayName.Replace(" ", ""); 
    if (key != "TabOne") 
    { 
     key = "TabTable"; 
    } 
    return win.FindResource(key) as DataTemplate; 
    } 
} 

使得TabOne返回DataTemplateTabOne,另外两个选项卡返回DataTemplateTabTable

如果我运行应用程序,点击每个选项卡的两次(1,2,3,1,2,3)我没有得到我所期望的,这是


塔博恩的视图中创建
TabTwo的视图中创建
塔博恩的观点是建立
TabTwo的视图中创建

也就是说,如果TemplateSelector返回不同的值,现有标签的控件都扔掉了,新的选项卡的控件的创建,如果TemplateSelector返回ns值相同,没有任何反应。

这正是我不想要的!我希望TabControl能够保留选项卡上的所有控件,并且我希望能够在代码中创建不同的控件,以便从TabTwoTabThree。没有后者,我可以生活。但是如何告诉TabControl不选择每个选项卡的控件?

回答

4

这是TabControl的功能,是默认行为。

基本上,为了节省内存,TabControl卸载了其内容区域中的可视化树,并将其替换为新选项卡中新绑定的树。为了证明这一点,您可以听取模板中每个控件的Unload事件,并注意每次切换选项卡时它都会触发。

有可能你想覆盖此行为两个原因:

  1. 你相信会有一个显著的性能损失。
  2. 您正在失去控件的状态,因为正在丢失的任何视觉状态都不由ViewModel支持。

至于#1,你不应该担心。 CPU时间通常比RAM更便宜,默认行为依赖于资源等式的更便宜的一面。如果你还是觉得你真的不希望这种行为,你可以在这里看到覆盖它的一个例子: https://github.com/cefsharp/CefSharp/blob/master/CefSharp.Wpf.Example/Controls/NonReloadingTabControl.cs

不过,我认为这是一个“嗅觉”潜在的未来的性能问题,你应该花时间现在要搞清楚,而不是推迟计算出来。

对于#2,你有两个选择:

  1. 请通过保留该状态的视图模型确保每一个你想保全的财产(如IsSelected等)的支持。
  2. 为您绑定到的每个选项卡创建持久UserControl,而不是ViewModels(您的案例中的工作区)。在WAF的“Writer”示例中有一个例子:http://waf.codeplex.com/
+0

谢谢安德森 - 这是理由1(它只是感觉很贵)。我会顺其自然。 --Amaca – amaca 2010-02-10 18:31:53

+0

我需要解决#1,我们有datagrids是非常昂贵的设置每个选项卡更改。我如何告诉tabcontrol单独维护标签的内容并且不卸载它们? – DarkwingDuck 2011-10-04 23:57:02

+0

@DarkwingDuck:Telerik发现了一个黑客。不了解内存使用情况。因人而异。 http://www.pluralsight-training.net/community/blogs/eburke/archive/2009/04/30/keeping-the-wpf-tab-control-from-destroying-its-children.aspx我建议看看其中一个出色的WPF性能工具,用于查看您的perf是否在您认为的位置丢失。这里有一个链接:http://msdn.microsoft.com/en-us/library/aa969767.aspx – 2011-10-05 02:39:57