在TabItem中加载UserControl

Pit*_*k76 13 wpf user-controls mvvm tabitem

我有一个Usercontrol(TabUserControl),其中包含一个TabControl.UserControl的Viewmodel加载了Ob Obtable的TabItems集合.这些项目是另一个用户控件.当我只在tabcontrol中加载文本时没有问题,但是如何将其他用户控件加载到TabUserControl的tabitem中.我正在使用MVVM.

这是我的代码:

public class TabItem
{
    public string Header { get; set; }
    public object Content { get; set; } // object to allow all sort of items??
}
Run Code Online (Sandbox Code Playgroud)

TabUserControl的Viewmodel

public class TabViewModel
{
    public ObservableCollection<TabItem> Tabs {get;set;}

    public TabViewModel()
    {
        Tabs = new ObservableCollection<TabItem>();
        //Tabs.Add(new TabItem { Header = "Overview", Content = new OverviewViewModel() }); How to load a usercontrol here if it's in the ItemCollection?
        Tabs.Add(new TabItem { Header = "Overview", Content = "Bla bla bla" });
        Tabs.Add(new TabItem { Header = "Two", Content = "Two's content" });
    }
}
Run Code Online (Sandbox Code Playgroud)

然后是TabControl XAML:

<TabControl x:Name="_tabControl"
            ItemsSource="{Binding Tabs}">
  <TabControl.ItemContainerStyle>
    <Style TargetType="TabItem">
      <Setter Property="Header"
              Value="{Binding Header}" />
      <Setter Property="Content"
              Value="{Binding Content}" />
    </Style>
  </TabControl.ItemContainerStyle>
</TabControl>
Run Code Online (Sandbox Code Playgroud)

只要我不在tabItems集合中加载usercontrol的viewmodel,它就可以工作.如何将UserTabControl加载到TabItem?目的是每个tabitem都包含一个usercontrol.然后每个用户控件都会自己做.

希望有人可以帮助我,因为我是WPF的初学者.谢谢!

Rac*_*hel 34

理想情况下,TabControl.ItemsSource应将其设置为一个集合ViewModels,并且DataTemplates应该用于告诉WPF ViewModel使用特定的每个绘制每个UserControl.

这使您的业务逻辑(ViewModels)与您的UI完全分离(Views)

例如,

<TabControl x:Name="MyTabControl"
            ItemsSource="{Binding TabViewModels}"
            SelectedItem="{Binding SelectedTabViewModel}">

    <TabControl.Resources>
        <DataTemplate DataType="{x:Type my:ViewModelA}">
            <my:ViewAUserControl />
        </DataTemplate>
        <DataTemplate DataType="{x:Type my:ViewModelB}">
            <my:ViewBUserControl />
        </DataTemplate>
        <DataTemplate DataType="{x:Type my:ViewModelC}">
            <my:ViewCUserControl />
        </DataTemplate>
    </TabControl.Resources>

    <TabControl.ItemContainerStyle>
        <Style TargetType="TabItem">
            <Setter Property="Header" Value="{Binding Header}" />
        </Style>
    </TabControl.ItemContainerStyle>

</TabControl>
Run Code Online (Sandbox Code Playgroud)

包含TabControl的DataContext的ViewModel:

TabViewModels = new ObservableCollection<ITabViewModel>();
TabViewModels.Add(new ViewModelA { Header = "Tab A" });
TabViewModels.Add(new ViewModelB { Header = "Tab B" });
TabViewModels.Add(new ViewModelC { Header = "Tab C" });

SelectedTabViewModel = TabViewModels[0];
Run Code Online (Sandbox Code Playgroud)


Rav*_*tty 5

感谢雷切尔的回答。但它强制在编译时本身声明 DataContext。像您一样,在 TabControl 的 DataTemplate 中将每个视图与它们各自的视图模型相关联。当把它移到 ViewModel 时,我们可以实现动态的 View-ViewModel 链接。就是这样:

XAML:

<TabControl.ItemContainerStyle>
      <Style TargetType="TabItem">
          <Setter Property="Header" Value="{Binding Header}" />
          <Setter Property="Content" Value="{Binding Content}" />
      </Style>
</TabControl.ItemContainerStyle>
Run Code Online (Sandbox Code Playgroud)

虚拟机:

 public ObservableCollection<TabItem> TabItems { get; set; }
 public MainWindowViewModel()
        {
            TabItems = new ObservableCollection<TabItem>
            {
                new TabItem{Content = new TabAView() {DataContext = new TabAViewModel()}, Header = "Tab A"},
                new TabItem{Content = new TabBView(), Header = "Tab B"}
            };
        }
Run Code Online (Sandbox Code Playgroud)

我们甚至可以使用 Action 委托来延迟和仅在 Tab SelectionChangedEvent 时调用 TabItems 的初始化。如果 UserControl 视图有许多 UI 元素,这将节省大量内存。