我試圖讓我的頭繞MVVM,我目前卡在如何處理導航。導航框架和Combobox MVVM
目前我有一個頁面,並且在該頁面中是一個框架,該框架負責在各種其他頁面中組幀。導航以前用下拉框處理,選擇改變它將以這種方式導航。
我不知道我怎麼能做到這一點,而不需要觸摸模型視圖中的框架,最終會打破mvvm。
最後,我試圖完成的是,單擊組合框,選擇一個項目,然後在下面的框架導航到正確的視圖。
我沒有使用Prism或MVVM的任何其他框架,只是試圖手動完成。
我試圖讓我的頭繞MVVM,我目前卡在如何處理導航。導航框架和Combobox MVVM
目前我有一個頁面,並且在該頁面中是一個框架,該框架負責在各種其他頁面中組幀。導航以前用下拉框處理,選擇改變它將以這種方式導航。
我不知道我怎麼能做到這一點,而不需要觸摸模型視圖中的框架,最終會打破mvvm。
最後,我試圖完成的是,單擊組合框,選擇一個項目,然後在下面的框架導航到正確的視圖。
我沒有使用Prism或MVVM的任何其他框架,只是試圖手動完成。
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
。我們將通過爲它寫一個數據模板來顯示它。
讓我們假設你給ViewModelBase
類String 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
,這很簡單:假設你有一個NotesTabView
UserControl
這是一個視圖爲您NotesTabViewModel
,你可以定義這樣一個DataTemplate:
<DataTemplate DataType="{x:Type vm:NotesTabViewModel}">
<vw:NotesTabView />
</DataTemplate>
@EdPlunkett:作爲一種替代的DataTemplate對於每個視圖,您可以在框架視圖模型使用ViewModelToViewConverter像我一樣綁定到選定的頁面這裏:https://stackoverflow.com/a/31721236/475727
隱式DataTemplates和DataTemplateSelectors是WPF和XAML獨有的,所以人們認爲這是推薦的解決方案,但我認爲它不適合導航。它感覺不舒服,並且因違反DRY原則而聞起來有味道。
謝謝,我會看看那個。當然,這確實意味着有某種IoC設置。 –
但是,是的,如果隱式模板只能在WPF上工作,那麼它們在其他地方並不是很有用! –
因此,當我這樣做時,我從組合框中選擇一個項目,它將框架的內容更改爲它實例化的視圖模型的名稱,就好像它只是對它執行一個.tostring()方法。 整個DataTemplate定義了它如何顯示數據的正確性? 那麼,如果我已經創建了每個頁面的單獨視圖,所以它只需要移動到正確的視圖 – Tbooty
聽起來像它沒有找到你放在框架中的視圖模型類型的數據模板。你在App.xaml中合併你的datatemplants.xaml嗎? –
@Tbooty在我的回答中添加了App.xaml –