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

ama*_*aca 3 wpf xaml tabcontrol mvvm viewmodel

我正在为我的应用程序使用 MVVM 模式。的主窗口包括TabControl与所述DataContext映射到视图模型:

<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}" />
Run Code Online (Sandbox Code Playgroud)

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

这样就TabOne返回了DataTemplate. TabOne其他两个选项卡返回DataTemplate TabTable.

如果我运行应用程序并在每个选项卡上单击两次(1、2、3、1、2、3),我不会得到我期望的结果,即


TabOne 视图创建
TabTwo 视图创建
TabOne 视图创建
TabTwo 视图创建

也就是说,如果TemplateSelector返回不同的值,则现有选项卡的控件将被丢弃并创建新选项卡的控件,如果TemplateSelector返回相同的值,则什么也不会发生。

这正是我不想要的!我希望TabControl将所有控件保留在选项卡上,并且我希望能够在代码中为我从TabTwo到的情况下创建不同的控件TabThree。我可以没有后者。但是,TabControl当每个选项卡的控件未被选中时,我如何告诉它不要扔掉它?

And*_*mes 5

这是 的函数,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等)都由保留该状态的 ViewModel 支持。
  2. UserControl为您绑定到的每个选项卡创建一个持久化,而不是绑定到 ViewModel(在您的情况下为工作区)。WAF 的“Writer”示例中有一个示例:http : //waf.codeplex.com/