TabControl处理非活动选项卡上的控件

时间:2010-02-10 15:40:05

标签: wpf xaml mvvm viewmodel tabcontrol

我正在为我的应用程序使用MVVM模式。 MainWindow包含一个TabControlDataContext映射到ViewModel:

<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和其他两个标签返回DataTemplate TabTable

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


TabOne的视图已创建
TabTwo的视图已创建
TabOne的视图已创建
TabTwo的视图已创建

也就是说,如果TemplateSelector返回不同的值,则会丢弃现有选项卡的控件并创建新选项卡的控件,如果TemplateSelector返回相同的值,则不会发生任何事情。< / p>

这正是我不想要的!我希望TabControl保留标签上的所有控件,我希望能够在代码中为TabTwo转到{{ 1}}。我可以没有后者。但是,当未选中时,如何告诉TabThree不要丢弃每个标签的控件?

1 个答案:

答案 0 :(得分:4)

这是TabControl的函数,是默认行为。

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

您可能有两个原因需要覆盖此行为:

  1. 您认为会有明显的性能损失。
  2. 您正在丢失控件的状态,因为ViewModel不支持任何丢失的可视状态。
  3. 至于#1 ,你不应该担心。 CPU时间通常比RAM便宜,默认行为倾向于资源等式的更便宜的一面。如果你仍然觉得你真的不想要这种行为,你可以在这里看到一个覆盖它的例子: https://github.com/cefsharp/CefSharp/blob/master/CefSharp.Wpf.Example/Controls/NonReloadingTabControl.cs

    但是,我认为这可能是未来性能问题的一个“嗅觉”,你应该花时间搞清楚,而不是推迟搞清楚。

    对于#2 ,您有两种选择:

    1. 确保保留的所有属性(如IsSelected等)由保留该状态的ViewModel支持。
    2. 为您绑定的每个标签创建一个持久UserControl,而不是ViewModels(在您的情况下为工作空间)。在WAF的“Writer”示例中有一个例子:http://waf.codeplex.com/