TabControl располагает элементами управления на неактивных вкладках
Я использую шаблон 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 ответ
Это функция TabControl
и поведение по умолчанию.
В основном, чтобы сохранить память, TabControl
выгружает визуальное дерево, которое находится в его области содержимого, и заменяет его новым созданным для новой вкладки. Чтобы доказать это себе, вы можете послушать Unload
Событие на каждом элементе управления в вашем шаблоне и обратите внимание, что он срабатывает при каждом переключении вкладок.
Вероятно, есть две причины, по которым вы хотите изменить это поведение:
- Вы считаете, что будет существенное снижение производительности.
- Вы теряете состояние элементов управления, потому что любое визуальное состояние, которое теряется, не поддерживается моделью представления.
Что касается # 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/