Я хочу создать TabControl, где TabItem будет динамически создаваться во время выполнения. TabItem должен быть связан с ViewModel. Эта модель представления поддерживает интерфейс, который знает, как создать контент внутри TabItem. Таким образом, в основном TabItems может использовать любой элемент управления содержимым, определенный моделью просмотра во время выполнения. Я пробовал разные подходы, используя TabControl.ContentTemplate или ControlTemplate и ItemTemplate, но ни один из них не работает. Похоже, что в шаблоне подход должен знать тип содержимого внутри TabItem во время разработки, чтобы иметь возможность отображать себя. Связывание свойства в связанном контексте данных работает отлично, но Content Control не отображается. Можем ли мы просто вывести новый класс MyTabItem: TabItem и создать пользовательский контент и связать его с содержимым MyTabItem. Необходим любой общий подход, который может позволить модели представления создавать содержимое TabItems.WPF TabControl с поддержкой ViewModel Создание содержимого TabItem
ответ
Вы можете указать DataTemplate
для каждого типа, который может быть динамически добавлен в ваш TabControl
? Если это так, для вас что-то вроде этой работы?
(Обратите внимание, что TabControl
находит то же DataTemplate
для обоих ItemTemplate
(шаблон заголовка вкладки) и ContentTemplate
(отображаемого внутри содержимого вкладки шаблона). Это происходит потому, что мы не указали ни, поэтому WPF просто поднимается по дереву и находит тот же шаблон для обоих из нашего Grid.Resources
. Если вы хотите использовать другой шаблон для каждого, вы можете явно указать шаблон, который будет использоваться для ItemTemplate
, если это работает для вас, или используйте DataTemplateSelector
или аналогичные.)
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.Resources>
<DataTemplate DataType="{x:Type local:DescribableOne}">
<Grid Background="Red">
<TextBlock Text="{Binding Description}" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type local:DescribableTwo}">
<Grid Background="Blue">
<TextBlock Text="{Binding Description}" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type local:DescribableThree}">
<Grid Background="Green">
<TextBlock Text="{Binding Description}" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
</Grid.Resources>
<StackPanel Orientation="Horizontal">
<Button Command="{Binding AddOne}">Add One</Button>
<Button Command="{Binding AddTwo}">Add Two</Button>
<Button Command="{Binding AddThree}">Add Three</Button>
</StackPanel>
<TabControl Grid.Row="1" ItemsSource="{Binding DynamicallyGeneratedTabs}"/>
</Grid>
И вид модель:
public class TabControlViewModel
{
public TabControlViewModel()
{
AddOne = new RelayCommand(DoAddOne);
AddTwo = new RelayCommand(DoAddTwo);
AddThree = new RelayCommand(DoAddThree);
DynamicallyGeneratedTabs = new ObservableCollection<IDescribable>();
}
public ICommand AddOne { get; }
public ICommand AddTwo { get; }
public ICommand AddThree { get; }
public ObservableCollection<IDescribable> DynamicallyGeneratedTabs { get; }
private void DoAddOne()
{
DynamicallyGeneratedTabs.Add(new DescribableOne());
}
private void DoAddTwo()
{
DynamicallyGeneratedTabs.Add(new DescribableTwo());
}
private void DoAddThree()
{
DynamicallyGeneratedTabs.Add(new DescribableThree());
}
}
public interface IDescribable
{
string Description { get; }
}
public class DescribableOne : IDescribable
{
public DescribableOne()
{
Description = "One";
}
public string Description { get; }
}
public class DescribableTwo : IDescribable
{
public DescribableTwo()
{
Description = "Two";
}
public string Description { get; }
}
public class DescribableThree : IDescribable
{
public DescribableThree()
{
Description = "Three";
}
public string Description { get; }
}
Спасибо @simon за ответ. В примере, который вы опубликовали, мы знаем тип содержимого в шаблоне данных во время разработки (TextBlock). Где я не Типа. Ok, чтобы быть более конкретным, мои элементы табуляции должны отображать графики и некоторые другие субконтроллеры, такие как таблица. Однако я не знаю, сколько графиков будет отображаться во время разработки, это зависит от ViewModel. Я хочу указать ContentControl вместо TextBlock, но я думаю, что это не сработает. например,
ok .. Я мог бы получить свой CustomTabItem: TabItem и создать его содержимое в конструкторе, пройдя в модели представления. ViewModel создает элемент контента и назначает его содержимому tabitem. каковы плюсы и минусы такого подхода. Я не вижу ответов на этот подход в stackoverflow. Разрешение viewModel для создания содержимого tabItems кажется очень стандартной проблемой. –