WPF选项卡控件,启用ViewModel选项卡项内容创建

WPF选项卡控件,启用ViewModel选项卡项内容创建,wpf,data-binding,viewmodel,tabcontrol,tabitem,Wpf,Data Binding,Viewmodel,Tabcontrol,Tabitem,我想创建一个TabControl,其中TabItem将在运行时动态创建。选项卡项应与ViewModel关联。此视图模型支持一个知道如何在TabItem内创建内容的接口。因此,基本上TabItems可以在运行时接受视图模型决定的任何内容控件。我尝试过使用TabControl.ContentTemplate或ControlTemplate和ItemTemplate的不同方法,但都不起作用。模板方法似乎需要在设计时知道TabItem中的内容类型,以便能够呈现自己。关联数据上下文中属性的绑定工作正常,但

我想创建一个TabControl,其中TabItem将在运行时动态创建。选项卡项应与ViewModel关联。此视图模型支持一个知道如何在TabItem内创建内容的接口。因此,基本上TabItems可以在运行时接受视图模型决定的任何内容控件。我尝试过使用TabControl.ContentTemplate或ControlTemplate和ItemTemplate的不同方法,但都不起作用。模板方法似乎需要在设计时知道TabItem中的内容类型,以便能够呈现自己。关联数据上下文中属性的绑定工作正常,但不显示内容控件。 我们是否可以派生一个新类MyTabItem:TabItem并创建自定义内容并将其与MyTabItem的内容相关联。
需要任何允许视图模型创建TabItems内容的通用方法

您是否能够为可能动态添加到
TabControl
中的每种类型指定一个
DataTemplate
?如果是这样的话,你会喜欢这个工作吗

(请注意,
TabControl
ItemTemplate
(选项卡标题的模板)和
ContentTemplate
(显示在所选选项卡内容内的模板)查找相同的
DataTemplate
)。这是因为我们没有指定任何一个,所以WPF只是在树上遍历,并从
网格.Resources
中为这两个资源查找相同的模板。如果您想为每个资源使用不同的模板,您可以显式指定要用于
ItemTemplate
的模板(如果适用),或者使用
DataTemplateSelect或
或类似产品。)


加一
加两个
加三
以及视图模型:

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; }
}
公共类选项卡ControlViewModel
{
公共选项卡ControlViewModel()
{
AddOne=新中继命令(DoAddOne);
AddTwo=新的RelayCommand(DoAddTwo);
AddThree=新的中继命令(DoAddThree);
DynamicallyGeneratedTabs=新的ObservableCollection();
}
公共ICommand AddOne{get;}
public ICommand AddTwo{get;}
公共ICommand AddThree{get;}
public observeCollection动态生成的数据库{get;}
私有void DoAddOne()
{
DynamicallyGeneratedTabs.Add(新的descripbableone());
}
私有void DoAddTwo()
{
DynamicallyGeneratedTabs.Add(新的descripabletwo());
}
私有无效DoAddThree()
{
DynamicallyGeneratedTabs.Add(新的descripablethree());
}
}
公共接口可描述
{
字符串说明{get;}
}
公共类描述:IDescribable
{
公众舆论
{
Description=“一”;
}
公共字符串描述{get;}
}
公共类描述符二:IDescribable
{
公共描述
{
Description=“两个”;
}
公共字符串描述{get;}
}
公共类描述符三:IDescribable
{
公共描述
{
Description=“三”;
}
公共字符串描述{get;}
}

ok。。我可以派生CustomTabItem:TabItem,并通过传入视图模型在构造函数中创建其内容。ViewModel创建内容元素并将其指定给tabitem的内容。这种方法的优缺点是什么。我在stackoverflow上看不到任何答案。允许viewModel创建tabItems内容似乎是一个非常标准的问题。谢谢@simon的回答。在您发布的示例中,我们知道设计时数据模板中的内容类型(TextBlock)。我不喜欢那种类型。更具体地说,我的选项卡项需要显示图形和一些其他子控件,如表。但是,我不知道在设计时会显示多少个图形,这取决于ViewModel。我想指定一个ContentControl而不是TextBlock,但我想这是行不通的。e、 g像这样
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; }
}