Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在WPF中使用MVVM在页面和打开窗口之间导航?_C#_Wpf_Xaml_Mvvm - Fatal编程技术网

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是