UWP NavigationView 通过 MVVM 切换到另一个页面

UWP NavigationView switch to another page via MVVM

第一次从 WPF 切换到 UWP,我发现 UWP 的世界中确实存在像 SplitViewNavgiationView 这样很棒的控件。

为了更新我当前的家庭项目,我选择 NavigationView 控件作为我的主要 UI 控件来提供各种信息。 使用页面导航 (as shown here) 的代码隐藏非常简单,但对于我的用例,我想使用 MVVM(作为一个学习过程,不使用像 MVVMLIght 或类似的固件)。

目前,我的 NavigationView 看起来像这样;但我不知道如何通过页面在框架内进行更改(根据我的理解,我必须使用 NavigationService 但还没有找到一个易于理解的示例):

<NavigationView x:Name="nvTopLevelNav" Grid.Column="0" Grid.Row="1" Grid.RowSpan="3" IsPaneOpen="False"  IsPaneToggleButtonVisible="False" CompactModeThresholdWidth="0" IsBackButtonVisible="Collapsed" Background="Black" Foreground="Black"
        Loaded="nvTopLevelNav_Loaded"
        Margin="0,12,0,0"
        SelectionChanged="nvTopLevelNav_SelectionChanged"
        ItemInvoked="nvTopLevelNav_ItemInvoked"
        IsTabStop="False"
                IsSettingsVisible="False"
                AlwaysShowHeader="False"
        Header="asdasdaasdasdasd">
    <NavigationView.MenuItems>
        <NavigationViewItem Icon="Home" Content="Home" Tag="Home_Page" />
        <NavigationViewItem Icon="Globe" Content="Weather" Tag="Weather_Page" />
        <NavigationViewItem Content="My Agenda" Tag="Agenda_Page">
    <!-- some custom PathIcon -->
        </NavigationViewItem>
        <NavigationViewItem Icon="Contact" Content="My News" Tag="News_Page" />
    </NavigationView.MenuItems>
    <Frame x:Name="contentFrame"></Frame>
</NavigationView>

UWP NavigationView switch to another page via MVVM

根据您的要求,您可以使用 Windows Template Studio 创建包含 MVVM 模式和 NavigationService 的 UWP 项目。

private void OnItemInvoked(NavigationViewItemInvokedEventArgs args)
{
    if (args.IsSettingsInvoked)
    {
        NavigationService.Navigate(typeof(SettingsViewModel).FullName);
        return;
    }

    var item = _navigationView.MenuItems
                    .OfType<NavigationViewItem>()
                    .First(menuItem => (string)menuItem.Content == (string)args.InvokedItem);
    var pageKey = item.GetValue(NavHelper.NavigateToProperty) as string;
    NavigationService.Navigate(pageKey);
}

阅读我的博客,了解我在没有任何第 3 方的情况下提出的解决方案 api,还有 github 解决方案报告。

https://kwodarczyk.github.io/UwpWinUI3PageMVVMNavigation/

所有你需要的附件属性允许将视图模型类型传递给你的数据模板

public class ViewModelContext : DependencyObject
{
    public static readonly DependencyProperty TypeProperty =
    DependencyProperty.RegisterAttached(
      "ViewModelContext",
      typeof(Type),
      typeof(ViewModelContext),
      new PropertyMetadata(null)
    );
    public static void SetType(DependencyObject element, Type value)
    {
        element.SetValue(TypeProperty, value);
    }
    public static Type GetType(DependencyObject element)
    {
        return (Type)element.GetValue(TypeProperty);
    }
}

示例数据模板:

<DataTemplate x:Key="PageOne" viewModels:ViewModelContext.Type="viewModels:PageOneViewModel">
   <views:PageOne/>
</DataTemplate>

和自定义模板选择器,您可以在其中将模板与视图模型相匹配

public class CustomTemplateSelector : DataTemplateSelector
{
    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        if (item != null)
        {
            var viewModeltype = item.GetType();

            foreach (var rd in Application.Current.Resources.MergedDictionaries)
            {
                foreach (var value in rd.Values)
                {
                    if (value is DataTemplate dataTempate)
                    {
                        Type contexType = dataTempate.GetValue(ViewModelContext.TypeProperty) as Type;

                        if (contexType != null && contexType == viewModeltype)
                        {
                            return dataTempate;
                        }
                    }
                }
            }
        }
        return null;
    }
}