C# 如何在WPF中使用MVVM在页面和打开窗口之间导航?
我读过几篇文章、教程、例子。但我仍然无法在页面和窗口之间进行导航C# 如何在WPF中使用MVVM在页面和打开窗口之间导航?,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,我读过几篇文章、教程、例子。但我仍然无法在页面和窗口之间进行导航 > Visual Studio Community 2019 > .NET Framework: 4.7.2 为了简单起见,我有3个页面和1个窗口所有视图都是KIOSK应用程序的全屏视图。详情如下: MVVMApps.sln │ ├── PageInitialize.xaml ├── PageHome.xaml └──── PageSelectLanguage.xaml └── Win
> Visual Studio Community 2019
> .NET Framework: 4.7.2
为了简单起见,我有3个页面和1个窗口所有视图都是KIOSK应用程序的全屏视图。详情如下:
MVVMApps.sln
│
├── PageInitialize.xaml
├── PageHome.xaml
└──── PageSelectLanguage.xaml
└── WinMessage.xaml
我尝试了GalaSoft提供的MvvmLight,但仍停留在从PageInitialize.xaml
导航到PageHome.xaml
上。我刚刚发现,WPF的文章即将发布在INavigationService
上。我找到的大多数教程都是针对Xamarin的采样
另外,我使用Microsoft.Practices.ServiceLocation获得了未定义的程序集代码>我看到它在Enterprise上可用。在Nuget上,安装MvvmLight也将安装CommonServiceLocator
public class ViewModelLocator
{
private static bool initialized;
public ViewModelLocator()
{
//Fix to keep blend happy
if (initialized) { return; }
initialized = true;
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<PageInitializeViewModel>();
SimpleIoc.Default.Register<PageHomeViewModel>();
SimpleIoc.Default.Register<PageSelectLanguageViewModel>();
SimpleIoc.Default.Register<WinMessageViewModel>();
SetupNavigation();
}
public MainViewModel Main => ServiceLocator.Current.GetInstance<MainViewModel>();
public PageInitializeViewModel PageInitializeViewModel => ServiceLocator.Current.GetInstance<PageInitializeViewModel>();
public PageHomeViewModel PageHomeViewModel => ServiceLocator.Current.GetInstance<PageHomeViewModel>();
public WinMessageViewModel WinMessageViewModel=> ServiceLocator.Current.GetInstance<WinMessageViewModel>();
public static void Cleanup()
{
// TODO Clear the ViewModels
}
private void SetupNavigation()
{
var navigationService = new Helpers.NavigationService<Helpers.NavigationPage>();
navigationService.ConfigurePages();
SimpleIoc.Default.Register<Helpers.INavigationService<Helpers.NavigationPage>>(() => navigationService);
}
}
公共类ViewModelLocator
{
私有静态bool初始化;
公共ViewModelLocator()
{
//修复以保持混合的快乐
if(初始化){return;}
初始化=真;
ServiceLocator.SetLocatorProvider(()=>SimpleIoc.Default);
SimpleIoc.Default.Register();
SimpleIoc.Default.Register();
SimpleIoc.Default.Register();
SimpleIoc.Default.Register();
SimpleIoc.Default.Register();
设置导航();
}
public MainViewModel Main=>ServiceLocator.Current.GetInstance();
公共页面InitializeViewModel页面InitializeViewModel=>ServiceLocator.Current.GetInstance();
公共页面HomeViewModel页面HomeViewModel=>ServiceLocator.Current.GetInstance();
public WinMessageViewModel WinMessageViewModel=>ServiceLocator.Current.GetInstance();
公共静态无效清除()
{
//要清除ViewModels,请执行以下操作:
}
私有void SetupNavigation()
{
var navigationService=newhelpers.navigationService();
navigationService.ConfigurePages();
simpleoc.Default.Register(()=>navigationService);
}
}
我已经完成了一些没有MvvmLight的教程:-
每篇文章都使用不同的方法,因为我不熟悉它,一旦出现错误行并且没有Intellisense建议,我就无法继续找到解决方案
如果我有多个页面和窗口屏幕,在WPF中使用MVVM难吗?目前,我有一个完整的WPF应用程序,但它使用代码隐藏。我想转到MVVM,因为我已经读到MVVM比代码隐藏更好。单页MVVM并不像我以前做的那样是一个问题,当使用MVVM时它是非常棒的
如果导航几乎不可能有可行的答案,我应该保留在WPF中使用代码隐藏吗?从简单开始,现在将导航服务、ViewModelLocator和除基本功能以外的所有功能都设置在一边
无论如何,我会避免所有那些……定位器类。他们必然依赖反模式
只需先使用viewmodel和单个窗口应用程序
基本模式涉及一个MainWindow,其Datacontext为MainWindowViewModel。
您可能需要一个菜单或类似的东西,但您将要切换的部分是contentcontrol的内容
将ContentControl的Content属性绑定到mainwindowviewmodel上的公共对象属性。为了便于讨论,请调用CurrentViewModel
为要在其中切换的每个视图定义viewmodel和usercontrol。因此,HomeView和HomeViewModel、LoginView和LoginView模型。等等
在资源字典中,为每个视图创建一个数据模板,将usercontrol与其viewmodel的类型关联起来
public class MainWindowViewModel : INotifyPropertyChanged
{
public ObservableCollection<ViewChoice> ViewChoices { get; set; }
= new ObservableCollection<ViewChoice>
{
new ViewChoice{ Name="Page One", VM=new Page1ViewModel()},
new ViewChoice{ Name="Page Two", VM=new Page2ViewModel()},
};
private ViewChoice selectedViewChoice;
public ViewChoice SelectedViewChoice
{
get { return selectedViewChoice; }
set { selectedViewChoice = value; RaisePropertyChanged(); }
}
在app.xaml中合并此资源字典
导航
实例化所需类型的新viewmodel
将CurrentViewModel设置为该实例
然后它将被模板化到UI中
有很多不同的版本-它被称为viewmodel first,您应该能够轻松地在谷歌上搜索一些示例
这里有一个我写的目的稍有不同:
如果您确实需要页面,可以对页面使用类似的方法:
简化视图:
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Window.Resources>
<DataTemplate DataType="{x:Type local:Page1ViewModel}">
<local:Page1/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Page2ViewModel}">
<local:Page2/>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ListBox Name="ViewSelect"
ItemsSource="{Binding ViewChoices}"
SelectedItem="{Binding SelectedViewChoice, Mode=TwoWay}"
>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Frame Grid.Column="1"
Content="{Binding SelectedViewChoice.VM}"
NavigationUIVisibility="Hidden"
/>
</Grid>
</Window>
非常简化的viewmodel
public class MainWindowViewModel : INotifyPropertyChanged
{
public ObservableCollection<ViewChoice> ViewChoices { get; set; }
= new ObservableCollection<ViewChoice>
{
new ViewChoice{ Name="Page One", VM=new Page1ViewModel()},
new ViewChoice{ Name="Page Two", VM=new Page2ViewModel()},
};
private ViewChoice selectedViewChoice;
public ViewChoice SelectedViewChoice
{
get { return selectedViewChoice; }
set { selectedViewChoice = value; RaisePropertyChanged(); }
}
public类MainWindowViewModel:INotifyPropertyChanged
{
公共ObservableCollection视图选项{get;set;}
=新的可观测集合
{
新建视图选项{Name=“Page One”,VM=new Page1ViewModel()},
新建视图选项{Name=“Page Two”,VM=new Page2ViewModel()},
};
private ViewChoice Selected查看选择;
公共视图选项SelectedViewChoice
{
获取{return selectedViewChoice;}
设置{selectedViewChoice=value;RaisePropertyChanged();}
}
ps
如果你决定学习prism,我会从delegatecommand开始,直到你至少编写了一个wpf应用程序。
PRISM中有大量的功能,大多数应用程序实际上并没有从区域和动态合成中获益
如果您喜欢mvvmlight(我喜欢),那么对于core,您最好获得源代码并使用它。您需要commandWPF命名空间,这依赖于nuget包中的net old。不支持命令的版本将无法很好地执行重新查询
我希望这是足够的信息,而不会让人不知所措。要做到既清楚又不让人被信息淹没,这很难。从简单开始,现在就把导航服务、ViewModelLocator和除基础之外的所有东西都放在一边
无论如何,我会避免所有这些……定位器类。它们必然依赖于反模式IMO
只需先使用viewmodel和单个窗口应用程序
基本模式涉及一个主窗口,其Datacontext是