我想创建一个TabControl,其中TabItem将在运行时动态创建。TabItem应该与ViewModel相关联。这个视图模型支持一个接口,该接口知道如何在TabItem中创建内容。基本上,TabItems可以在运行时接受视图模型决定的任何内容控制。我尝试过使用TabControl的不同方法。ContentTemplate或ControlTemplate和ItemTemplate,但他们都没有工作。似乎模板方法需要在设计时知道TabItem内部内容的类型,以便能够呈现自己。关联数据上下文中的属性绑定工作正常,但不显示Content Control。我们可以派生一个新的类MyTabItem:TabItem并创建一个自定义内容,并将其与MyTabItem的内容相关联吗?任何允许视图模型创建TabItems内容的通用方法都是必需的。
您是否能够为可能动态添加到TabControl
的每种类型指定DataTemplate
?如果是这样,这样的东西适合你吗?
(注意,TabControl
为ItemTemplate
(选项卡标题的模板)和ContentTemplate
(在所选选项卡的内容中显示的模板)找到相同的DataTemplate
。这是因为我们都没有指定,所以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; }
}