2012-03-20 26 views
10

Tôi có một Usercontrol (TabUserControl) có chứa một TabControl. ViewModel của UserControl đó tải ab Bộ sưu tập quan sát được của TabItems. Một trong những mục đó là điều khiển người dùng khác. Khi tôi chỉ cần tải văn bản trong tabcontrol không có vấn đề, nhưng làm thế nào tôi có thể tải điều khiển người dùng khác vào tabitem của TabUserControl. Tôi đang sử dụng MVVM.Tải UserControl trong TabItem

Dưới đây là mã của tôi:

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

ViewModel của 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" }); 
    } 
} 

Và sau đó 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> 

Nó hoạt động miễn là tôi không tải viewmodel của usercontrol trong bộ sưu tập tabItems. làm thế nào tôi có thể làm cho UserTabControl tải trên TabItem? Mục đích là mỗi tabitem sẽ chứa một usercontrol. Mỗi usercontrol sau đó làm điều riêng của nó.

Hy vọng ai đó có thể giúp tôi vì tôi là người mới bắt đầu WPF. Thx!

Trả lời

27

Lý tưởng nhất, các TabControl.ItemsSource nên được đặt thành một bộ sưu tập của ViewModels, và DataTemplates nên được sử dụng để nói với WPF để vẽ mỗi ViewModel với một cụ UserControl.

Điều này sẽ giúp giữa logic kinh doanh của bạn (ViewModels) hoàn toàn tách biệt với giao diện người dùng của bạn (Views)

Ví dụ,

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

ViewModel chứa DataContext TabControl của:

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

Xin chào Rachel. Thx cho ý kiến ​​của bạn. Tôi hiểu logic bạn đang nói, nhưng tôi có một chút vất vả để làm cho nó hoạt động. Đặc biệt là một phần của ITabViewModel, bạn lấy nó từ đâu? Một phần khác của câu hỏi của tôi là làm thế nào tôi có thể làm điều này nếu tôi không biết có bao nhiêu tab nên được thêm vào? Tôi luôn luôn chắc chắn về một ít nhất một tab, nhưng các tab khác nên được thêm vào khi tôi nhấp vào một nút .. Thx cho sự giúp đỡ của bạn. – PitAttack76

+0

@ Stieven76 'ITabViewModel' đơn giản là giao diện xác định thuộc tính' Header'. Các ViewModels A, B và C sẽ kế thừa từ 'ITabViewModel', vì vậy tất cả chúng đều chia sẻ cùng một lớp cơ sở.Vì bạn đang sử dụng MVVM, thuộc tính 'Command' của Button nên trỏ đến một lệnh trong' ViewModel', nó sẽ đơn giản thêm một đối tượng mới vào bộ sưu tập 'TabViewModels', và có thể thiết lập nó như được chọn. – Rachel

+0

Thx Rachel. Tôi đã làm nó theo cách tôi muốn. Thx để được giúp đỡ! – PitAttack76

2

Cảm ơn Rachel cho câu trả lời của bạn. Nhưng nó thực thi khai báo DataContext trong suốt thời gian biên dịch. Giống như bạn đã làm, liên quan đến từng Chế độ xem với Chế độ xem tương ứng của chúng trong DataTemplate của TabControl. Chúng ta có thể đạt được liên kết View-ViewModel động khi di chuyển sang ViewModel. Đây là cách:

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

Chúng tôi thậm chí có thể tận dụng các đại biểu hành động để trì hoãn và gọi khởi tạo của TabItems chỉ khi Tab SelectionChangedEvent. Điều này đạt được rất nhiều bộ nhớ tiết kiệm nếu xem UserControl có nhiều yếu tố giao diện người dùng.

Các vấn đề liên quan