How is Navigation from ContentDialog to a different page in UWP which uses Template10 MVVM possible?

668 views Asked by At

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 <== Code behind

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));

    }
}
}
  • The above work is what I have tried. I also tried to navigate to the main page using NavigationService.Navigate(typeof(Views.MainPage)); but it is also not working.
  • Any help is appreciated
  • I am able to navigate to mainpage using the function navigatetomain() but the content dialog doesnt close even though i am trying to Hide(); and also after navigation I am not able to see my hamburger menu in my Mainpage its just a blank mainpage.

NOTE: The Hide(); in code behind for close button works perfect.

2

There are 2 answers

0
Faraaz bhilwade On BEST ANSWER

Instead of having a button of my own [Button_Login_click] I used the primarybuttonclick of contentdialog and using relaycommand declared in LoginPageCDViewModel.cs I Binded the primarybuttoncommand property to the relaycommand button declared in LoginPageCDViewModel.cs

So now my LoginPageCD.xaml looks like

<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">
   .
   .
   .

and for navigation to the desired page I am making use of the result of the contentdialog box i.e I am calling the ShowAsync(); at the start of the app and after recognizing the primary click I am using NavigationService.Navigate(typeof(Views.MainPage)); to navigate.

4
Richard Zhang On

I'm looking at your code, but it looks like it commented out some content. Here are some of my thoughts:

  1. Keep the uniqueness of ViewModel

I noticed that you created 3 LoginPageCDViewModel in ContentDialog related code, namely ContentDialog.Resources, viewModelBase and LPVM.

This may cause confusion, you can try to create only a LoginPageCDViewModel and set it as DataContext, which can be bound in XAML.

  1. Unknown reference to LoginPageContentD

When you try to close the ContentDialog, the code used is LoginPageContentD.Hide(). But I did not find the definition of this variable in the code you provided.

Does it refer to the current ContentDialog? You can use debug breakpoints to track the code to see if the reference is normal.

  • If it is called inside ContentDialog, you can directly use this.Hide().
  • If this is a variable that represents the current ContentDialog instance, then it should be assigned a value when ContentDialog is started, like:
public LoginPageCD()
{
    this.InitializeComponent();
    ViewModelBase viewModelBase = new LoginPageCDViewModel();
    this.DataContext = viewModelBase;
    dict = ResourceLoader.GetForCurrentView("Login");
    viewModelBase.UpdateUserNameList();

    viewModelBase.LoginPageContentD = this;
}

If the above suggestions can't solve your problem, can you provide a minimum runnable demo (does not contain private information, but can run and reproduce the problem) so that we can test and analyze the cause?