2016-05-19 93 views
1

我想在我的MainView中顯示TabControlItems中的不同視圖。MVVM將視圖綁定到TabControlItems - 視圖不顯示

要做到這一點,我創建了一個類是這樣的:

public sealed class TabItem 
{ 
    public string Header { get; set; } 
    public ViewModelBase Content { get; set; } 
} 

那我在List調用我的視圖模型:

private ObservableCollection<TabItem> _views; 
public ObservableCollection<TabItem> Views 
{ 
    get { return _views; } 
    set 
    { 
     _views = value; 
     RaisePropertyChanged(() => Views); 
    } 
} 

public IndexMainViewModel() 
{ 
    Views = new ObservableCollection<TabItem>(); 
    Views.Add(new TabItem { Header = "Export", Content = new ExportViewModel() }); 
    Views.Add(new TabItem { Header = "Import", Content = new ImportViewModel() }); 
} 

編輯然後在我的視圖中顯示:

<window xmlns:views="clr-namespace:EDICOT_Module_Import_Export_Articles.View" 
xmlns:vm="clr-namespace:EDICOT_Module_Import_Export_Articles.ViewModel" 
xmlns:model="clr-namespace:EDICOT_Module_Import_Export_Articles.Model.Classes" 
DataContext="{Binding IndexMainVM, Source={StaticResource Locator}}"> 

    <TabControl ItemsSource="{Binding Views}"> 
    <TabControl.Resources> 
     <DataTemplate DataType="{x:Type model:TabItem}"> 
      <DataTemplate.Resources> 
       <DataTemplate DataType="{x:Type vm:ImportViewModel}"> 
        <views:ImportView /> 
       </DataTemplate> 
       <DataTemplate DataType="{x:Type vm:ExportViewModel}"> 
        <views:ExportView /> 
       </DataTemplate> 
      </DataTemplate.Resources> 
      <ContentControl Content="{Binding Content}"/> 
     </DataTemplate> 
    </TabControl.Resources> 

    <TabControl.ItemTemplate > 
     <DataTemplate > 
      <TextBlock Text="{Binding Header}"/> 
     </DataTemplate> 
    </TabControl.ItemTemplate> 
</TabControl> 

問題是,它只顯示標題但不顯示內容(視圖),它顯示的是TabItem類的路徑。

爲了給更多的信息:我截斷了代碼,只保留主題需要的內容,並使用MVVM Light。

我真的不明白我在這裏想念的東西! Thx爲您提供幫助。

+0

編輯代碼工作。 – RizzCandy

回答

2

問題是每個選項卡都綁定到TabItem的實例。您的數據模板爲vm:ExportViewModelvm:ImportViewModel。你現在看到你的錯誤嗎?

有很多解決方案。最簡單的方法是將Header文本移動到基本視圖模型中,並將該Tab控件綁定到ViewModel的集合。

另一種替代方法是爲TabItem添加DataTemplate,將ContentControl粘貼在其中,並將綁定到視圖模型。下面是一些XAML般的僞代碼來說明這個道理:

<DataTemplate DataType="{x:Type vm:TabItem}"> 
    <ContentControl Content={Binding Content}" /> 
</DataTemplate> 

您可能需要爲您的視圖模型模板移動到ContentControl中的資源,但我不認爲這是必要的。您可能需要調整TabItem數據模板,以便它也填充選項卡窗口。

一個第三辦法是實現一個自定義DataTemplateSelector和使用在你的標籤控制。在這個選擇器中,簡單地打開你的TabItem並查看該類型的Content屬性。您可以瀏覽默認DataTemplateSelector的源代碼,以瞭解如何獲取給定類型的正確模板。這種方法讓你的手深陷WPF的痛處,這是一次有趣的旅行。 我已經做了一次,我寧願不要再做一次。其實,爲了您的需要,這次旅行不會像我一樣糟糕。 默認選擇器不會蹲下,所以返回base.SelectTemplate是毫無價值的。我在框架中挖掘了應該如何實施的例子。

public class TabItemDataTemplateSelector : DataTemplateSelector 
{ 
    public override DataTemplate 
     SelectTemplate(object item, DependencyObject container) 
    { 
     var viewModel = item as TabItem; 
     if (item == null) 
      return null; 
     else 
      item = viewModel.Content; 

     FrameworkElement fe = null; 
     if (container is ContentPresenter) 
      fe = (container as ContentPresenter) 
        .TemplatedParent as FrameworkElement; 
     else 
      fe = container as FrameworkElement; 

     var key = new DataTemplateKey(item.GetType()); 
     return fe.TryFindResource(key) as DataTemplate; 
    } 
} 

者的一個實例添加到資源的地方

<derp:TabItemDataTemplateSelector x:Key="tidts"/> 

然後綁定,爲ContentTemplateSelector

<TabControl ItemsSource="{Binding Views}" 
      ContentTemplateSelector={StaticResource tidts}> 
+0

thx很多爲您的答案,我猜這樣的事情'instabiating' TabItems'但它仍然有點灰暗的時刻你可以精確一點?我會更接近你的第一個和第二個解決方案,如果它能正常工作,我會進行編輯。對於第三種解決方案,您是否有更多解釋或樣本? - Thx mate – RizzCandy

+0

@RizzCandy默認的DataTemplateSelector查看綁定中對象的類型,然後在可視化樹中查找其DataType屬性與此類型匹配的DataTemplate。它對你的TabItem或它的Content屬性一無所知。添加了一些c#和xaml像僞代碼應該引導你。 – Will

+0

Thx很多,但我嘗試了許多沒有成功的解決方案,並得出了這樣的結論:因爲我使用MVVM Light,即使在我的TabItem集合中有ViewModel,我的TabItem屬性'ViewModelBase'也是未定義的。所以當視圖中調用內容時,它不知道要顯示什麼內容。目前我不知道如何解決這個問題! – RizzCandy