我目前正在開發一個C#WPF應用程序,並試圖遵循MVVM設計模式。處理WPF MVVM中ContentControls之間導航的更好方法?
它現在的工作方式是我在我的主窗口中使用ContentControl
並將其綁定到CurrentViewModel
,並在我的數據模板中聲明App.xaml
。當我想在主窗口中更改當前視圖時,我所要做的就是在主窗口的視圖模型中更改CurrentViewModel
屬性,這非常合適。此外,爲了不直接引用視圖模型(在視圖模型中通過執行new blablaViewModel()
),我有一個單例FlowManager
類,我在ICommand
函數中調用,並且實例化在該類中完成,而不是在視圖中完成模型。
這種方法的問題,是因爲我添加到我的應用程序的每個觀點,我要補充一個DataTemplate在App.xaml
,在我FlowManager
類的enum
條目,並在我的switch()
新case
在ChangePage()
功能,新的ICommand在我的MainViewModel
中,除了添加實際視圖的代碼並創建它自己的視圖模型之外。
下面是我如何處理我的申請流程爲例:
在MainWindow.xaml,我有以下佈局:
<Window x:Class="EveExcelMineralUpdater.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModels="clr-namespace:EveExcelMineralUpdater.ViewModels"
Title="MainWindow" Height="720" Width="1280">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15*"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="85*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<Button>MarketStat Request</Button>
<Button Command="{Binding ChangeToQuickLookCommand}">QuickLook Request</Button>
<Button>History Request</Button>
<Button>Route Request</Button>
<Button>Settings</Button>
</StackPanel>
<Separator Grid.Column="1" Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" />
<ContentControl Grid.Column="2" Content="{Binding CurrentViewModel}" />
</Grid>
</Window>
在App.xaml.cs我通過創建主窗口並設置其啓動應用程序DataContext
和MainViewModel
屬性:
MainWindow mainWindow = new MainWindow();
MainViewModel mainViewModel = new MainViewModel();
mainWindow.DataContext = mainViewModel;
mainWindow.ViewModel = mainViewModel;
FlowManager.Instance.AppWindow = mainWindow;
mainWindow.Show();
在MainViewModel.cs,我處理一個按鈕請求與ICommand
想換個CurrentView
屬性如下:
private void ChangeToQuickLook(object param)
{
FlowManager.Instance.ChangePage(FlowManager.Pages.QuickLook);
}
...
public ICommand ChangeToQuickLookCommand
{
get { return new RelayCommand(ChangeToQuickLook); }
}
在FlowManager.cs,我有一個enum
,列出所有頁面(視圖)在我的應用程序,並實際ChangePage()
功能,這將改變CurrentViewModel
財產在我MainViewModel
:
// Only one view is implemented for now, the rest are empty for now
public void ChangePage(Pages page)
{
IViewModel newViewModel = null;
switch (page)
{
case Pages.MarketStat:
break;
case Pages.QuickLook:
newViewModel = new QuickLookRequestViewModel();
break;
case Pages.History:
break;
case Pages.Route:
break;
case Pages.Settings:
break;
}
AppWindow.ViewModel.CurrentViewModel = newViewModel;
}
...
public enum Pages
{
MarketStat,
QuickLook,
History,
Route,
Settings
}
最後,在App.xaml中,我有我所有的DataTemplates我所有的意見的清單:
<Application x:Class="EveExcelMineralUpdater.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModels="clr-namespace:EveExcelMineralUpdater.ViewModels"
xmlns:views="clr-namespace:EveExcelMineralUpdater.Views"
Startup="App_OnStartup">
<Application.Resources>
<!-- Pages DataTemplates -->
<DataTemplate DataType="{x:Type viewModels:QuickLookRequestViewModel}">
<views:QuickLookRequestView />
</DataTemplate>
</Application.Resources>
</Application>
就像我說的,這個效果很好,但我可以看到一些可擴展性問題,因爲我有修改我的代碼的幾個部分,以便在應用程序中添加視圖。沒有使用任何框架,有沒有更好的方法來做到這一點?
您可以查看我的導航源代碼:https://github.com/Maxikq/WKFramework#navigation-for-wpf –
@WojciechKulik感謝您的建議,我會研究它! – Choub890