如何从 ContentDialog 导航到 UWP 中使用 Template10 MVVM 的不同页面?
How is Navigation from ContentDialog to a different page in UWP which uses Template10 MVVM possible?
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,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, Mode=TwoWay, 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();
非常完美。
我正在查看您的代码,但它似乎注释掉了一些内容。以下是我的一些想法:
- 保持ViewModel的唯一性
我注意到您在ContentDialog相关代码中创建了3个LoginPageCDViewModel
,分别是ContentDialog.Resources
、viewModelBase
和LPVM
.
这可能会造成混淆,你可以尝试只创建一个LoginPageCDViewModel
并设置为DataContext
,可以在XAML.
中绑定
- 对
LoginPageContentD
的未知引用
当您尝试关闭 ContentDialog 时,使用的代码是 LoginPageContentD.Hide()
。但是我在你提供的代码中没有找到这个变量的定义。
是否引用当前的ContentDialog?可以使用debug断点跟踪代码看引用是否正常
- 如果在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;
}
如果以上建议不能解决您的问题,能否提供一个最低运行可用的demo(不包含隐私信息,但可以运行并重现问题)以便我们可以测试分析原因吗?
我没有使用自己的按钮 [Button_Login_click] 我使用了 contentdialog 的 primarybuttonclick 并使用了在 LoginPageCDViewModel.cs
中声明的 relaycommand 我将 primarybuttoncommand 属性 绑定到声明的 relaycommand 按钮在 LoginPageCDViewModel.cs
所以现在我的 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">
.
.
.
为了导航到所需的页面,我正在使用内容对话框的结果,即我在应用程序开始时调用 ShowAsync();
,在识别出我使用的主要点击后 NavigationService.Navigate(typeof(Views.MainPage));
导航。
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,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, Mode=TwoWay, 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();
非常完美。
我正在查看您的代码,但它似乎注释掉了一些内容。以下是我的一些想法:
- 保持ViewModel的唯一性
我注意到您在ContentDialog相关代码中创建了3个LoginPageCDViewModel
,分别是ContentDialog.Resources
、viewModelBase
和LPVM
.
这可能会造成混淆,你可以尝试只创建一个LoginPageCDViewModel
并设置为DataContext
,可以在XAML.
- 对
LoginPageContentD
的未知引用
当您尝试关闭 ContentDialog 时,使用的代码是 LoginPageContentD.Hide()
。但是我在你提供的代码中没有找到这个变量的定义。
是否引用当前的ContentDialog?可以使用debug断点跟踪代码看引用是否正常
- 如果在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;
}
如果以上建议不能解决您的问题,能否提供一个最低运行可用的demo(不包含隐私信息,但可以运行并重现问题)以便我们可以测试分析原因吗?
我没有使用自己的按钮 [Button_Login_click] 我使用了 contentdialog 的 primarybuttonclick 并使用了在 LoginPageCDViewModel.cs
中声明的 relaycommand 我将 primarybuttoncommand 属性 绑定到声明的 relaycommand 按钮在 LoginPageCDViewModel.cs
所以现在我的 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">
.
.
.
为了导航到所需的页面,我正在使用内容对话框的结果,即我在应用程序开始时调用 ShowAsync();
,在识别出我使用的主要点击后 NavigationService.Navigate(typeof(Views.MainPage));
导航。