Вопрос по wpf, viewmodel, xaml, mvvm, tabcontrol – TabControl располагает элементами управления на неактивных вкладках

3

Я использую шаблон MVVM для моего приложения. Главное окно содержитTabControl сDataContext сопоставлены с 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 возвращаетDataTemplate. TabOne а две другие вкладки возвращаютDataTemplate TabTable.

Если я запускаю приложение и нажимаю на каждую из вкладок дважды (1, 2, 3, 1, 2, 3), я не получаю то, что ожидаю, что


Представление TabOne создано
Представление TabTwo создано
TabOne's View создан
Представление TabTwo создано

то есть еслиTemplateSelector возвращает другое значение, элементы управления существующей вкладки выбрасываются и создаются элементы управления новой вкладки, и еслиTemplateSelector возвращает то же значение, ничего не происходит.

Это именно то, чего я не хочу! Я хотел быTabControl сохранить все элементы управления на вкладках, и я хотел бы иметь возможность сделать что-то о создании различных элементов управления в коде для случая, когда я иду изTabTwo вTabThree, Я могу жить без последнего. Но как мне сказатьTabControl не выбрасывать элементы управления каждой вкладки, когда она не выбрана?

Ваш Ответ

1   ответ
4

Это функцияTabControl и поведение по умолчанию.

В основном, чтобы сохранить память,TabControl выгружает визуальное дерево, которое находится в его области содержимого, и заменяет его новым созданным для новой вкладки. Чтобы доказать это себе, вы можете послушатьUnload событие на каждом элементе управления в вашем шаблоне и обратите внимание, что он срабатывает при каждом переключении вкладок.

Вероятно, есть две причины, по которым вы хотите изменить это поведение:

Вы считаете, что будет существенное снижение производительности.Вы теряете состояние элементов управления, потому что любое визуальное состояние, которое теряется, не поддерживается ViewModel.

Что касается# 1Вы не должны быть обеспокоены. Время ЦП, как правило, дешевле, чем ОЗУ, а поведение по умолчанию опирается на более дешевую сторону уравнения ресурсов. Если вы все еще чувствуете, что ДЕЙСТВИТЕЛЬНО не хотите такого поведения, вы можете увидеть пример переопределения здесь:https://github.com/cefsharp/CefSharp/blob/master/CefSharp.Wpf.Example/Controls/NonReloadingTabControl.cs

Тем не менее, я бы посчитал это «запахом» для потенциальной проблемы с производительностью в будущем, которую вы должны потратить на то, чтобы выяснить это сейчас, а не откладывать на выяснение.

За# 2У вас есть два варианта:

Убедитесь, что каждое свойство, которое вы хотите сохранить (например,IsSelectedи т. д.) поддерживается моделью ViewModel, которая сохраняет это состояние.Создать постоянныйUserControl для каждой вкладки, к которой вы привязываетесь, а не к ViewModels (рабочие области в вашем случае). Вот пример этого в образце «Writer» для WAF:http://waf.codeplex.com/
@Anderson Imes - Ваша ссылка на Telerik не работает. dcp
Спасибо Андерсон - это была причина 1 (это просто кажется дорогим). Я пойду с потоком. --Amaca amaca
@dcp вот альтернатива на GitHub:github.com/cefsharp/CefSharp/blob/master/CefSharp.Wpf.Example/... Anderson Imes
Мне нужно решить # 1, у нас есть сетки данных, которые очень дороги для установки при каждом изменении вкладки. Как я могу сказать tabcontrol поддерживать содержимое вкладок индивидуально, а не выгружать их? DarkwingDuck
@DarkwingDuck: Telerik нашел взломать, похоже. Понятия не имею об использовании памяти. YMMV.pluralsight-training.net/community/blogs/eburke/archive/2009/04/... Я бы порекомендовал взглянуть на один из превосходных инструментов производительности WPF, чтобы увидеть, теряется ли ваш перфинг там, где вы думаете. Вот ссылка на это:msdn.microsoft.com/en-us/library/aa969767.aspx Anderson Imes

Похожие вопросы