Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Latest commit

 

History

History
77 lines (63 loc) · 2.67 KB

multi-paged-dialogs.md

File metadata and controls

77 lines (63 loc) · 2.67 KB

Multi-paged Dialogs

Some dialogs will be multi-paged - for example the login dialog has a credentials page and a 2Fa page that is shown if two-factor authorization is required.

The View Model

To help implement view models for a multi-page dialog there is a useful base class called PagedDialogViewModelBase. The typical way of implementing this is as follows:

  • Define each page of the dialog as you would implement a single dialog view model
  • Implement a "container" view model for the dialog that inherits from PagedDialogViewModel
  • Import each page into the container view model
  • Add logic to switch between pages by setting the PagedDialogViewModelBase.Content property
  • Add a Done observable

Here's a simple example of a container dialog that has two pages. The pages are switched using ReactiveCommands:

using System;
using System.ComponentModel.Composition;

namespace GitHub.ViewModels.Dialog
{
    [Export(typeof(IExamplePagedDialogViewModel))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class ExamplePagedDialogViewModel : PagedDialogViewModelBase,
                                               IExamplePagedDialogViewModel
    {
        [ImportingConstructor]
        public ExamplePagedDialogViewModel(
            IPage1ViewModel page1,
            IPage2ViewModel page2)
        {
            Content = page1;
            page1.Next.Subscribe(_ => Content = page2);
            page2.Previous.Subscribe(_ => Content = page1);
            Done = Observable.Merge(page2.Done, page2.Done);
        }

        public override IObservable<object> Done { get; }
    }
}

The View

The view in this case is very simple: it just needs to display the Content property of the container view model:

<UserControl x:Class="GitHub.VisualStudio.Views.Dialog.ExamplePagedDialogView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Content="{Binding Content}">
</UserControl>
using System;
using System.ComponentModel.Composition;
using System.Windows.Controls;
using GitHub.Exports;
using GitHub.ViewModels.Dialog;

namespace GitHub.VisualStudio.Views.Dialog
{
    [ExportViewFor(typeof(IExamplePagedDialogViewModel))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public partial class ExamplePagedDialogView : UserControl
    {
        public NewLoginView()
        {
            InitializeComponent();
        }
    }
}

Note: this is such a common pattern, you don't actually need to define your own view! Simply add the [ExportViewFor(...)] attribute to the existing ContentView class.