如何从ContentDialog导航到使用Template10 MVVM的UWP中的其他页面?

问题描述

LoginPageCD.xaml

<ContentDialog
x:Class="ScanWorx.ContentDialogs.LoginPageCD"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ScanWorx.ContentDialogs"
xmlns:vm="using:ScanWorx.viewmodels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Name="LoginPageContentD"
SecondaryButtonText="close"
SecondaryButtonClick="LoginPageContentD_SecondaryButtonClick">

<ContentDialog.Resources>
    <Thickness x:Key="ContentDialogPadding">16,16,16</Thickness>
    <vm:LoginPageCDviewmodel x:Key="CDviewmodel"  />
</ContentDialog.Resources>

<!--  Content Dialog Title  -->
<ContentDialog.TitleTemplate>
    <DataTemplate >

        <TextBlock
            HEADER DATA FOR TEMPLATE/>

    </DataTemplate>
</ContentDialog.TitleTemplate>

<ContentControl x:Name="LoginPageContentControl" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <ContentControl.ContentTemplate>
        <DataTemplate>
            <Grid Width="500" Height="500">
                <Grid.RowDeFinitions>
                    <RowDeFinition />
                    <RowDeFinition />
                    <RowDeFinition Height="1*" />
                </Grid.RowDeFinitions>

                <ComboBox
                    x:Name="ComboBox_Login_test"
                    Grid.Row="0"
                    Header="ComboBox_Login.Header"
                    IsEditable="True"
                    ItemsSource = "{Binding UserNameList,Source = {StaticResource CDviewmodel}}" 
                    Text="{Binding Name,Source = {StaticResource CDviewmodel},FallbackValue=DesigntimeValue,Mode=TwoWay}"/>

                <PasswordBox
                    x:Name="PasswordBox_Login"
                    Grid.Row="1"
                    Header="PasswordBox_Login.Header"
                    Password="{Binding Passwort,Mode=TwoWay,Source= {StaticResource CDviewmodel}}" />

                <Button
                    x:Name="Button_Login_Click"
                    Grid.Row="2"
                    Command="{Binding LoginButtonCommand,Source= {StaticResource CDviewmodel}}"
                    Style="{ThemeResource AccentButtonStyle}"/>

            </Grid>
        </DataTemplate>
    </ContentControl.ContentTemplate>
</ContentControl>

LoginPageCD.xaml.cs 代码背后

using ScanWorx.viewmodels;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.ApplicationModel.Resources;
using Template10.Mvvm;

namespace ScanWorx.ContentDialogs
{

public partial class LoginPageCD : ContentDialog
{

    public LoginPResult Result { get; set; }

    public static ResourceLoader dict;
    public LoginPageCD()
    {
        this.InitializeComponent();
        viewmodelBase viewmodelBase = new LoginPageCDviewmodel();
        this.DataContext = viewmodelBase;
        dict = ResourceLoader.GetForCurrentView("Login");
        LoginPageCDviewmodel LPVM = new LoginPageCDviewmodel();
        LPVM.UpdateUserNameList();
    }


    private void LoginPageContentD_SecondaryButtonClick(ContentDialog sender,ContentDialogButtonClickEventArgs args)
    {
        Frame rootFrame = Window.Current.Content as Frame;
        rootFrame = new Frame();
        Window.Current.Content = rootFrame;
        rootFrame.Navigate(typeof(Views.LoginPage));

        LoginPageContentD.Hide();
       
    }

}
}

LoginPageCDviewmodel.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Xml;
using Template10.Mvvm;
using Template10.Services.NavigationService;
using Windows.ApplicationModel.Resources;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.UI.Popups;
using Windows.UI.Xaml.Navigation;
using System.Linq;
using Windows.UI.Xaml;
using Template10.Utils;

namespace ScanWorx.viewmodels
{
class LoginPageCDviewmodel : viewmodelBase
{
    public static ObservableCollection<string> _UserNameList = new ObservableCollection<string>();
    public ObservableCollection<string> UserNameList { get { return _UserNameList; } set { Set(ref _UserNameList,value); } }

    private string _Name = "";
    private string _Passwort = "";

    public RelayCommand LoginButtonCommand
    {
        get;
        private set;
    }

    public string Name { get { return _Name; } set { Set(ref _Name,value); } }
    public string Passwort { get { return _Passwort; } set { Set(ref _Passwort,value); } }


    public static ResourceLoader dict;

    public ObservableCollection<string> UpdateUserNameList()
    {
        try
        {
            **A FUNCTION TO UPDATE THE USER's LIST IN THE COMBOBox**
            **USAGE: USED IN CODE BEHIND WHILE INITIALIZING THE CONTENT DIALOG**
        }
        catch
        {
            Debug.WriteLine("Catch Exeption:  LoginPage.xaml.cs     Invalid UserManagement.xml file");
        }
        return _UserNameList;
    }

    public LoginPageCDviewmodel()
    {
        if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
        {
            Value = "Designtime value";
        }
        Services.SettingsServices.SettingsService.Instance.IsFullScreen = true;

        LoginButtonCommand = new RelayCommand(Button_Login_Click,() => true);

        dict = ResourceLoader.GetForCurrentView("Login");
    }
 
    public async void Button_Login_Click()
    {
        try
        {
                **ACTION: some code to check the username and password**

                loginPageCDviewmodel.navigatetomain();        //<<<<// a function to navigate to main page which doesnt work     
                //NavigationService.Navigate(typeof(Views.MainPage));

        }
        catch
        {
            Debug.WriteLine("Catch Exeption:  LoginPageCDviewmodel.cs     Button_Login_Click");
        }
    }

    public void navigatetomain()
    {
        Frame rootFrame = Window.Current.Content as Frame;
        rootFrame = new Frame();
        Window.Current.Content = rootFrame;
        rootFrame.Navigate(typeof(Views.MainPage));
        LoginPageContentD.Hide();

        //NavigationService.Navigate(typeof(Views.MainPage));

    }
}
}
  • 以上工作是我尝试过的。我还尝试使用NavigationService.Navigate(typeof(Views.MainPage));导航到主页,但是它也无法正常工作。
  • 感谢您的帮助
  • 我可以使用功能navigatetomain()导航到主页,但是即使我尝试Hide();内容对话框也不会关闭,而且导航后我也看不到自己的汉堡菜单主页只是一个空白的主页。

注意:后面代码中用于关闭按钮的Hide();很完美。

解决方法

我正在查看您的代码,但是它似乎注释掉了一些内容。这是我的一些想法:

  1. 保持ViewModel的唯一性

我注意到您在ContentDialog相关代码中创建了3个LoginPageCDViewModel,即ContentDialog.ResourcesviewModelBaseLPVM

这可能会引起混乱,您可以尝试仅创建一个LoginPageCDViewModel并将其设置为DataContext,可以在XAML中对其进行绑定。

  1. 未知引用LoginPageContentD

当您尝试关闭ContentDialog时,使用的代码为LoginPageContentD.Hide()。但是我在您提供的代码中找不到此变量的定义。

它是否引用当前的ContentDialog?您可以使用调试断点来跟踪代码,以查看引用是否正常。

  • 如果在ContentDialog中调用它,则可以直接使用this.Hide()
  • 如果这是代表当前ContentDialog实例的变量,则在启动ContentDialog时应为其分配一个值,例如:
public LoginPageCD()
{
    this.InitializeComponent();
    ViewModelBase viewModelBase = new LoginPageCDViewModel();
    this.DataContext = viewModelBase;
    dict = ResourceLoader.GetForCurrentView("Login");
    viewModelBase.UpdateUserNameList();

    viewModelBase.LoginPageContentD = this;
}

如果上述建议不能解决您的问题,您能否提供一个最低限度的可运行演示(不包含私人信息,但可以运行并重现问题),以便我们可以测试和分析原因?

,

我没有使用自己的按钮[Button_Login_click],而是使用contentdialog的primarybuttonclick并使用了LoginPageCDViewModel.cs中声明的relaycommand我将primarybuttoncommand属性绑定到了LoginPageCDViewModel.cs中声明的relaycommand按钮上。

所以现在我的LoginPageCD.xaml看起来像

<ContentDialog
    x:Class="ScanWorx.ContentDialogs.LoginPageCD"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:ScanWorx.ContentDialogs"
    xmlns:vm="using:ScanWorx.ViewModels"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    x:Name="LoginPageContentD"
    PrimaryButtonCommand="{x:Bind Path=vm:LoginPageViewModel.LoginButtonCommand }"
    PrimaryButtonText="Login"
    SecondaryButtonText="close"
    SecondaryButtonClick="LoginPageContentD_SecondaryButtonClick">
   .
   .
   .

,为了导航到所需页面,我利用contentdialog框的结果,即我在应用程序启动时调用ShowAsync();,并在识别出主要点击后使用{{1} }进行导航。