2016-05-16 131 views
0

我試圖讓我的頭繞MVVM,我目前卡在如何處理導航。導航框架和Combobox MVVM

目前我有一個頁面,並且在該頁面中是一個框架,該框架負責在各種其他頁面中組幀。導航以前用下拉框處理,選擇改變它將以這種方式導航。

我不知道我怎麼能做到這一點,而不需要觸摸模型視圖中的框架,最終會打破mvvm。

最後,我試圖完成的是,單擊組合框,選擇一個項目,然後在下面的框架導航到正確的視圖。

我沒有使用Prism或MVVM的任何其他框架,只是試圖手動完成。

回答

1

ComboBox將顯示ObservableCollection由您的主視圖模型公開的框架項目,並且視圖模型將具有所選項目的另一個屬性。

您的主視圖模型和框架項目viewmodels都從ViewModelBase類繼承,該類實現了INotifyPropertyChanged,也許還有其他一些東西。

所以,C#:

public ObservableCollection<ViewModelBase> FrameItems { get; protected set; } 

private ViewModelBase _selectedFrameItem; 
public ViewModelBase SelectedFrameItem { 
    get { return _selectedFrameItem; } 
    set { 
     value = _selectedFrameItem; 
     // Defined in ViewModelBase 
     OnPropertyChanged(); 
    } 
} 

你的主要視圖模型將在其構造填充FrameItems

public MainViewModel() 
{ 
    FrameItems = new ObservableCollection<ViewModelbase> { 
     new IceCreamMenu(), 
     new SmurfOptions(), 
     new MagicSparklePonyFourierTransformConfiguration() 
    }; 
} 

每一幀產品的ViewModelBase一個子類。它公開了屬性與通知,包括它可能具有的任何一組子對象的ObservableCollections。我們將通過爲它寫一個數據模板來顯示它。

讓我們假設你給ViewModelBaseString Title { get; set; }屬性。或者,也許你會想寫一個ViewModelBase的子類,它引入了Title;你的來電。現在讓我們把它放在ViewModelBase爲簡單起見。

XAML - 這樣就省去了所有的佈局,但您不需要這裏。

<ComboBox 
    ItemsSource="{Binding FrameItems}" 
    SelectedItem="{Binding SelectedFrameItem}" 
    DisplayMemberPath="Title" 
    /> 

<Frame Content={Binding SelectedFrameItem}" /> 

好的,但怎麼知道該怎麼辦SelectedFrameItem?!

簡單!編寫一個名爲ViewModelDataTemplates.xaml的資源字典,並將其合併到App.xaml中,以使其內容在應用程序的任何XAML中「可見」。

的App.xaml

<Application.Resources> 
    <ResourceDictionary> 
     <ResourceDictionary.MergedDictionaries> 
      <!-- Source is a relative path from project root directory --> 
      <ResourceDictionary Source="ViewModelDataTemplates.xaml" /> 
     </ResourceDictionary.MergedDictionaries> 
    </ResourceDictionary> 
</Application.Resources> 

...加任何東西,主題或什麼。

ViewModelDataTemplates.xaml中,爲您的框架項目類定義數據模板。

假設你有一個IceCreamMenu視圖模型,用Flavors

public ObservableCollection<IceCreamFlavor> Flavors { get; protected set; } 

集合......和SelectedFlavor。您可以在資源字典中使用xmlns:vm屬性適當地定義名稱空間vm

ViewModelDataTemplates.xaml

<DataTemplate DataType="{x:Type vm:IceCreamMenu}"> 
    <Grid> 
     <ListBox 
      ItemsSource="{Binding Flavors}" 
      SelectedItem="{Binding SelectedFlavor}" 
      /> 
    </Grid> 
</DataTemplate> 

<DataTemplate DataType="{x:Type vm:IceCreamFlavor}"> 
    <StackPanel Orientation="Horizontal"> 
     <Border 
      Height="20" 
      Width="20" 
      Margin="4" 
      Background={Binding Color, Converter={StaticResource ColorToBrushConverter}}" 
      /> 
     <Label Content="Name" /> 
    </StackPanel> 
</DataTemplate> 

如果你有現有的要通過的DataTemplates使用UserControls,這很簡單:假設你有一個NotesTabViewUserControl這是一個視圖爲您NotesTabViewModel,你可以定義這樣一個DataTemplate:

<DataTemplate DataType="{x:Type vm:NotesTabViewModel}"> 
    <vw:NotesTabView /> 
</DataTemplate> 
+0

因此,當我這樣做時,我從組合框中選擇一個項目,它將框架的內容更改爲它實例化的視圖模型的名稱,就好像它只是對它執行一個.tostring()方法。 整個DataTemplate定義了它如何顯示數據的正確性? 那麼,如果我已經創建了每個頁面的單獨視圖,所以它只需要移動到正確的視圖 – Tbooty

+0

聽起來像它沒有找到你放在框架中的視圖模型類型的數據模板。你在App.xaml中合併你的datatemplants.xaml嗎? –

+0

@Tbooty在我的回答中添加了App.xaml –

0

@EdPlunkett:作爲一種替代的DataTemplate對於每個視圖,您可以在框架視圖模型使用ViewModelToViewConverter像我一樣綁定到選定的頁面這裏:https://stackoverflow.com/a/31721236/475727

隱式DataTemplates和DataTemplateSelectors是WPF和XAML獨有的,所以人們認爲這是推薦的解決方案,但我認爲它不適合導航。它感覺不舒服,並且因違反DRY原則而聞起來有味道。

+0

謝謝,我會看看那個。當然,這確實意味着有某種IoC設置。 –

+0

但是,是的,如果隱式模板只能在WPF上工作,那麼它們在其他地方並不是很有用! –