2012-03-20 35 views
10

我有一個UserControl(TabUserControl),它包含一個TabControl。該UserControl的Viewmodel加載ab Observable集合的TabItems。其中一個od是另一個用戶控件。當我在tabcontrol中加載文本時沒有問題,但是如何將其他用戶控件加載到TabUserControl的tabitem中。 我正在使用MVVM。在TabItem中加載UserControl

這裏是我的代碼:

public class TabItem 
{ 
    public string Header { get; set; } 
    public object Content { get; set; } // object to allow all sort of items?? 
} 

的TabUserControl

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" }); 
    } 
} 

視圖模型然後是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> 

它的工作原理,只要我不加載視圖模型tabItems集合中的用戶控件。我如何使UserTabControl加載到TabItem? 意圖是每個tabitem都會包含一個usercontrol。每個用戶控件然後做它自己的事情。

希望有人可以幫助我,因爲我是WPF初學者。 Thx!

回答

27

理想情況下,TabControl.ItemsSource應被設置爲ViewModels的集合,並且DataTemplates應該用來告訴WPF繪製每個ViewModel與特定UserControl

這樣可以使你的業務邏輯(ViewModels)完全獨立間從你的UI(Views

例如,包含的TabControl的DataContext的

<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> 

視圖模型:

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]; 
+0

嗨Rachel。 Thx爲您的評論。我理解你說的邏輯,但我努力讓它運作起來。特別是ITabViewModel的一部分,你從哪裏得到?我的問題的另一部分是我如何做到這一點,如果我不知道應該添加多少標籤?我總是肯定至少有一個標籤,但是當我點擊一個按鈕時應該添加其他標籤。Thx爲您提供幫助。 – PitAttack76 2012-03-21 14:35:13

+0

@ Stieven76 ITabViewModel只是一個定義Header屬性的接口。 ViewModels A,B和C都會從'ITabViewModel'繼承,所以他們都會共享相同的基類。由於您使用的是MVVM,Button的'Command'屬性應該指向'ViewModel'中的一個命令,該命令只會將一個新對象添加到'TabViewModels'集合中,並且可能將其設置爲選中狀態。 – Rachel 2012-03-21 14:40:11

+0

Thx Rachel。我已經按照我想要的方式工作了。 Thx的幫助! – PitAttack76 2012-03-21 15:42:48

2

感謝雷切爾的你的答案。但它在編譯時本身強制聲明DataContext。像你一樣,將每個視圖與TabControl的DataTemplate中各自的ViewModels相關聯。將其移出到ViewModel時,我們可以實現動態View-ViewModel鏈接。具體方法如下:

XAML:

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

VM:

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"} 
      }; 
     } 

我們甚至可以利用行動代表延遲並且僅在標籤SelectionChangedEvent調用的TabItems的初始化。如果UserControl Views包含很多UI元素,則可以節省大量內存。

相關問題