Click here to Skip to main content
Click here to Skip to main content

Showing Dialogs When Using the MVVM Pattern

, 5 Oct 2010
Rate this:
Please Sign up or sign in to vote.
A solution for how to solve the problem of opening dialogs from a ViewModel when using the MVVM pattern.

Contents

Introduction

This article will address one of the problems a developer might run into when using the MVVM pattern, namely opening dialogs from ViewModels. Basic knowledge of the pattern is expected. Josh Smith has written a fantastic article in MSDN Magazine which can serve as the starting point for those that are unfamiliar with the pattern.

There already exist some solutions exploring this area, but none of them seem to be widely accepted among the MVVM community. Onyx on CodePlex is probably the most complete solution. Sacha Barber announced that he is working on a new MVVM framework, but hasn't set any release date. At the same time, WPF Disciples are teaming up to create a MVVM reference application, again with no release date yet.

My Interpretation of MVVM

I am possibly sticking my neck out here, but I would like to state some of my own interpretations of the MVVM pattern:

  • The fundamental core is the separation of UI and logic. ViewModel and View can communicate using bindings, making it possible for the View to be happily unaware of the ViewModel and vice versa. I know some of you might say: "well, actually the View knows about the ViewModel since the ViewModel is stored within the DataContext property, and the View is declaring its bindings to match properties on the ViewModel, surely the View must know the ViewModel?". I don't think so; we have to analyze what knows actually means. The ViewModel is stored in the DataContext property, that is correct, but DataContext is of type Object. From the View's point, the only thing it knows is whether the property has been set or not, nothing about the actual content. Let's get to the bindings declared in the View; do they say something about the ViewModel? I would have to say no here as well. The View might declare whatever bindings it wishes, but the ViewModel isn't enforced to implement them.
  • The ViewModel should serve the View with data, but one might argue where the separation between the View and ViewModel is. If for instance the ViewModel is holding a list of items presented in a ListView, I would argue that sorting, grouping, and filtering could be the responsibility of the View, not the ViewModel. Attached properties can solve this for us, making the ViewModel happily unaware of the item presentation.
  • The ViewModel should not contain anything used purely in tests; either a class is testable or it isn't.

The Dialog Service

The concept of letting services handle relations between the ViewModel and View seems to be the most accepted solution. My contribution is IDialogService.

/// <summary>
/// Interface responsible for abstracting ViewModels from Views.
/// </summary>
public interface IDialogService
{
  /// <summary>
  /// Gets the registered views.
  /// </summary>
  ReadOnlyCollection<FrameworkElement> Views { get; }

  /// <summary>
  /// Registers a View.
  /// </summary>
  /// <param name="view">The registered View.</param>
  void Register(FrameworkElement view);

  /// <summary>
  /// Unregisters a View.
  /// </summary>
  /// <param name="view">The unregistered View.</param>
  void Unregister(FrameworkElement view);

  /// <summary>
  /// Shows a dialog.
  /// </summary>
  /// <remarks>
  /// The dialog used to represent the ViewModel is retrieved from the registered mappings.
  /// </remarks>
  /// <param name="ownerViewModel">
  /// A ViewModel that represents the owner window of the dialog.
  /// </param>
  /// <param name="viewModel">The ViewModel of the new dialog.</param>
  /// <returns>
  /// A nullable value of type bool that signifies how a window was closed by the user.
  /// </returns>
  bool? ShowDialog(object ownerViewModel, object viewModel);

  /// <summary>
  /// Shows a dialog.
  /// </summary>
  /// <param name="ownerViewModel">
  /// A ViewModel that represents the owner window of the dialog.
  /// </param>
  /// <param name="viewModel">The ViewModel of the new dialog.</param>
  /// <typeparam name="T">The type of the dialog to show.</typeparam>
  /// <returns>
  /// A nullable value of type bool that signifies how a window was closed by the user.
  /// </returns>
  bool? ShowDialog<T>(object ownerViewModel, object viewModel) where T : Window;

  /// <summary>
  /// Shows a message box.
  /// </summary>
  /// <param name="ownerViewModel">
  /// A ViewModel that represents the owner window of the message box.
  /// </param>
  /// <param name="messageBoxText">A string that specifies the text to display.</param>
  /// <param name="caption">A string that specifies the title bar caption to display.</param>
  /// <param name="button">
  /// A MessageBoxButton value that specifies which button or buttons to display.
  /// </param>
  /// <param name="icon">A MessageBoxImage value that specifies the icon to display.</param>
  /// <returns>
  /// A MessageBoxResult value that specifies which message box button is clicked by the user.
  /// </returns>
  MessageBoxResult ShowMessageBox(
    object ownerViewModel,
    string messageBoxText,
    string caption,
    MessageBoxButton button,
    MessageBoxImage icon);

  /// <summary>
  /// Shows the OpenFileDialog.
  /// </summary>
  /// <param name="ownerViewModel">
  /// A ViewModel that represents the owner window of the dialog.
  /// </param>
  /// <param name="openFileDialog">The interface of a open file dialog.</param>
  /// <returns>DialogResult.OK if successful; otherwise DialogResult.Cancel.</returns>
  DialogResult ShowOpenFileDialog(object ownerViewModel, IOpenFileDialog openFileDialog);

  /// <summary>
  /// Shows the FolderBrowserDialog.
  /// </summary>
  /// <param name="ownerViewModel">
  /// A ViewModel that represents the owner window of the dialog.
  /// </param>
  /// <param name="folderBrowserDialog">The interface of a folder browser dialog.</param>
  /// <returns>The DialogResult.OK if successful; otherwise DialogResult.Cancel.</returns>
  DialogResult ShowFolderBrowserDialog(object ownerViewModel, 
               IFolderBrowserDialog folderBrowserDialog);
}

The actual implementation of IDialogServiceis is DialogService.

/// <summary>
/// Class responsible for abstracting ViewModels from Views.
/// </summary>
class DialogService : IDialogService
{
  private readonly HashSet<FrameworkElement> views;
  private readonly IWindowViewModelMappings windowViewModelMappings;

  /// <summary>
  /// Initializes a new instance of the <see cref="DialogService"/> class.
  /// </summary>
  /// <param name="windowViewModelMappings">
  /// The window ViewModel mappings. Default value is null.
  /// </param>
  public DialogService(IWindowViewModelMappings windowViewModelMappings = null)
  {
    this.windowViewModelMappings = windowViewModelMappings;

    views = new HashSet<FrameworkElement>();
  }

  #region IDialogService Members

  /// <summary>
  /// Gets the registered views.
  /// </summary>
  public ReadOnlyCollection<FrameworkElement> Views
  {
    get { return new ReadOnlyCollection<FrameworkElement>(views.ToList()); }
  }

  /// <summary>
  /// Registers a View.
  /// </summary>
  /// <param name="view">The registered View.</param>
  public void Register(FrameworkElement view)
  {
    // Get owner window
    Window owner = GetOwner(view);
    if (owner == null)
    {
      // Perform a late register when the View hasn't been loaded yet.
      // This will happen if e.g. the View is contained in a Frame.
      view.Loaded += LateRegister;
      return;
    }

    // Register for owner window closing, since we then should unregister View reference,
    // preventing memory leaks
    owner.Closed += OwnerClosed;

    views.Add(view);
  }

  /// <summary>
  /// Unregisters a View.
  /// </summary>
  /// <param name="view">The unregistered View.</param>
  public void Unregister(FrameworkElement view)
  {
    views.Remove(view);
  }

  /// <summary>
  /// Shows a dialog.
  /// </summary>
  /// <remarks>
  /// The dialog used to represent the ViewModel is retrieved from the registered mappings.
  /// </remarks>
  /// <param name="ownerViewModel">
  /// A ViewModel that represents the owner window of the dialog.
  /// </param>
  /// <param name="viewModel">The ViewModel of the new dialog.</param>
  /// <returns>
  /// A nullable value of type bool that signifies how a window was closed by the user.
  /// </returns>
  public bool? ShowDialog(object ownerViewModel, object viewModel)
  {
    Type dialogType = 
      windowViewModelMappings.GetWindowTypeFromViewModelType(viewModel.GetType());
    return ShowDialog(ownerViewModel, viewModel, dialogType);
  }

  /// <summary>
  /// Shows a dialog.
  /// </summary>
  /// <param name="ownerViewModel">
  /// A ViewModel that represents the owner window of the dialog.
  /// </param>
  /// <param name="viewModel">The ViewModel of the new dialog.</param>
  /// <typeparam name="T">The type of the dialog to show.</typeparam>
  /// <returns>
  /// A nullable value of type bool that signifies how a window was closed by the user.
  /// </returns>
  public bool? ShowDialog<T>(object ownerViewModel, object viewModel) where T : Window
  {
    return ShowDialog(ownerViewModel, viewModel, typeof(T));
  }

  /// <summary>
  /// Shows a message box.
  /// </summary>
  /// <param name="ownerViewModel">
  /// A ViewModel that represents the owner window of the message box.
  /// </param>
  /// <param name="messageBoxText">A string
  /// that specifies the text to display.</param>
  /// <param name="caption">A string that specifies
  /// the title bar caption to display.</param>
  /// <param name="button">
  /// A MessageBoxButton value that specifies which button or buttons to display.
  /// </param>
  /// <param name="icon">A MessageBoxImage value
  /// that specifies the icon to display.</param>
  /// <returns>
  /// A MessageBoxResult value that specifies which
  /// message box button is clicked by the user.
  /// </returns>
  public MessageBoxResult ShowMessageBox(
    object ownerViewModel,
    string messageBoxText,
    string caption,
    MessageBoxButton button,
    MessageBoxImage icon)
  {
    return MessageBox.Show(FindOwnerWindow(ownerViewModel), 
                           messageBoxText, caption, button, icon);
  }

  /// <summary>
  /// Shows the OpenFileDialog.
  /// </summary>
  /// <param name="ownerViewModel">
  /// A ViewModel that represents the owner window of the dialog.
  /// </param>
  /// <param name="openFileDialog">The interface of a open file dialog.</param>
  /// <returns>DialogResult.OK if successful;
  /// otherwise DialogResult.Cancel.</returns>
  public DialogResult ShowOpenFileDialog(object ownerViewModel, 
                      IOpenFileDialog openFileDialog)
  {
    // Create OpenFileDialog with specified ViewModel
    OpenFileDialog dialog = new OpenFileDialog(openFileDialog);

    // Show dialog
    return dialog.ShowDialog(new WindowWrapper(FindOwnerWindow(ownerViewModel)));
  }

  /// <summary>
  /// Shows the FolderBrowserDialog.
  /// </summary>
  /// <param name="ownerViewModel">
  /// A ViewModel that represents the owner window of the dialog.
  /// </param>
  /// <param name="folderBrowserDialog">The interface
  ///           of a folder browser dialog.</param>
  /// <returns>The DialogResult.OK if successful;
  ///       otherwise DialogResult.Cancel.</returns>
  public DialogResult ShowFolderBrowserDialog(object ownerViewModel, 
                      IFolderBrowserDialog folderBrowserDialog)
  {
    // Create FolderBrowserDialog with specified ViewModel
    FolderBrowserDialog dialog = new FolderBrowserDialog(folderBrowserDialog);

    // Show dialog
    return dialog.ShowDialog(new WindowWrapper(FindOwnerWindow(ownerViewModel)));
  }

  #endregion

  #region Attached properties

  /// <summary>
  /// Attached property describing whether
  /// a FrameworkElement is acting as a View in MVVM.
  /// </summary>
  public static readonly DependencyProperty IsRegisteredViewProperty =
    DependencyProperty.RegisterAttached(
    "IsRegisteredView",
    typeof(bool),
    typeof(DialogService),
    new UIPropertyMetadata(IsRegisteredViewPropertyChanged));

  /// <summary>
  /// Gets value describing whether FrameworkElement is acting as View in MVVM.
  /// </summary>
  public static bool GetIsRegisteredView(FrameworkElement target)
  {
    return (bool)target.GetValue(IsRegisteredViewProperty);
  }

  /// <summary>
  /// Sets value describing whether FrameworkElement is acting as View in MVVM.
  /// </summary>
  public static void SetIsRegisteredView(FrameworkElement target, bool value)
  {
    target.SetValue(IsRegisteredViewProperty, value);
  }

  /// <summary>
  /// Is responsible for handling IsRegisteredViewProperty changes, i.e. whether
  /// FrameworkElement is acting as View in MVVM or not.
  /// </summary>
  private static void IsRegisteredViewPropertyChanged(DependencyObject target,
    DependencyPropertyChangedEventArgs e)
  {
    // The Visual Studio Designer or Blend will run this code when setting the attached
    // property, however at that point there is no IDialogService registered
    // in the ServiceLocator which will cause
    /// the Resolve method to throw a ArgumentException.
    if (DesignerProperties.GetIsInDesignMode(target)) return;

    FrameworkElement view = target as FrameworkElement;
    if (view != null)
    {
      // Cast values
      bool newValue = (bool)e.NewValue;
      bool oldValue = (bool)e.OldValue;

      if (newValue)
      {
        ServiceLocator.Resolve<IDialogService>().Register(view);
      }
      else
      {
        ServiceLocator.Resolve<IDialogService>().Unregister(view);
      }
    }
  }

  #endregion

  /// <summary>
  /// Shows a dialog.
  /// </summary>
  /// <param name="ownerViewModel">
  /// A ViewModel that represents the owner window of the dialog.
  /// </param>
  /// <param name="viewModel">The ViewModel of the new dialog.</param>
  /// <param name="dialogType">The type of the dialog.</param>
  /// <returns>
  /// A nullable value of type bool that signifies how a window was closed by the user.
  /// </returns>
  private bool? ShowDialog(object ownerViewModel, object viewModel, Type dialogType)
  {
    // Create dialog and set properties
    Window dialog = (Window)Activator.CreateInstance(dialogType);
    dialog.Owner = FindOwnerWindow(ownerViewModel);
    dialog.DataContext = viewModel;

    // Show dialog
    return dialog.ShowDialog();
  }

  /// <summary>
  /// Finds window corresponding to specified ViewModel.
  /// </summary>
  private Window FindOwnerWindow(object viewModel)
  {
    FrameworkElement view = 
      views.SingleOrDefault(v => ReferenceEquals(v.DataContext, viewModel));
    if (view == null)
    {
      throw new ArgumentException("Viewmodel is not referenced by any registered View.");
    }

    // Get owner window
    Window owner = view as Window;
    if (owner == null)
    {
      owner = Window.GetWindow(view);
    }

    // Make sure owner window was found
    if (owner == null)
    {
      throw new InvalidOperationException("View is not contained within a Window.");
    }

    return owner;
  }

  /// <summary>
  /// Callback for late View register.
  /// It wasn't possible to do a instant register since the
  /// View wasn't at that point part of the logical nor visual tree.
  /// </summary>
  private void LateRegister(object sender, RoutedEventArgs e)
  {
    FrameworkElement view = sender as FrameworkElement;
    if (view != null)
    {
      // Unregister loaded event
      view.Loaded -= LateRegister;

      // Register the view
      Register(view);
    }
  }

  /// <summary>
  /// Handles owner window closed, View service should then unregister all Views acting
  /// within the closed window.
  /// </summary>
  private void OwnerClosed(object sender, EventArgs e)
  {
    Window owner = sender as Window;
    if (owner != null)
    {
      // Find Views acting within closed window
      IEnumerable<FrameworkElement> windowViews =
        from view in views
        where Window.GetWindow(view) == owner
        select view;

      // Unregister Views in window
      foreach (FrameworkElement view in windowViews.ToArray())
      {
        Unregister(view);
      }
    }
  }

  /// <summary>
  /// Gets the owning Window of a view.
  /// </summary>
  /// <param name="view">The view.</param>
  /// <returns>The owning Window if found; otherwise null.</returns>
  private Window GetOwner(FrameworkElement view)
  {
    return view as Window ?? Window.GetWindow(view);
  }
}

The design is pretty straightforward. A View is registering itself as part of the MVVM pattern by setting the attached property IsRegisteredView on any element in the logical tree.

<Window
  x:Class="MVVM_Dialogs.View.MainWindow"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:service="clr-namespace:MVVM_Dialogs.Service"
  service:DialogService.IsRegisteredView="True">

The View is now remembered by the dialog service. When a ViewModel is in need to show some kind of dialog, the correct View is found by the service, and its owning Window is used as the owner.

Showing a Dialog from a ViewModel

There exist two overloads for using the ShowDialog method. The first one lets the developer specify the dialog type.

public class MainWindowViewModel : ViewModelBase
{
  ...

  private void ShowInformation(object o)
  {
    // Get the selected person ViewModel
    PersonViewModel selectedPerson = persons.Single(p => p.IsSelected);

    // Create the PersonDialog ViewModel
    PersonDialogViewModel personDialogViewModel = 
              new PersonDialogViewModel(selectedPerson.Person);

    // Showing the dialog, alternative 1.
    // Showing a specified dialog. This doesn't require any form of mapping using 
    // IWindowViewModelMappings.
    dialogService.ShowDialog<PersonDialog>(this, personDialogViewModel);
  }
}

This overload specifies that a PersonDialog should be displayed with this as the owner and personDialogViewModel as DataContext. However, some of you might find it unsuitable that a View is specified in a ViewModel. For you, there is a second overload.

public class MainWindowViewModel : ViewModelBase
{
  ...

  private void ShowInformation(object o)
  {
    // Get the selected person ViewModel
    PersonViewModel selectedPerson = persons.Single(p => p.IsSelected);

    // Create the PersonDialog ViewModel
    PersonDialogViewModel personDialogViewModel = 
                new PersonDialogViewModel(selectedPerson.Person);

    // Showing the dialog, alternative 2.
    // Showing a dialog without specifying the type.
    // This require some form of mapping using 
    // IWindowViewModelMappings.
    dialogService.ShowDialog(this, personDialogViewModel);
  }
}

/// <summary>
/// Class describing the Window-ViewModel mappings used by the dialog service.
/// </summary>
public class WindowViewModelMappings : IWindowViewModelMappings
{
  private IDictionary<Type, Type> mappings;

  /// <summary>
  /// Initializes a new instance of the <see cref="WindowViewModelMappings"/> class.
  /// </summary>
  public WindowViewModelMappings()
  {
    mappings = new Dictionary<Type, Type>
    {
      { typeof(PersonDialogViewModel), typeof(PersonDialog) }
    };
  }

  /// <summary>
  /// Gets the window type based on registered ViewModel type.
  /// </summary>
  /// <param name="viewModelType">The type of the ViewModel.</param>
  /// <returns>The window type based on registered ViewModel type.</returns>
  public Type GetWindowTypeFromViewModelType(Type viewModelType)
  {
    return mappings[viewModelType];
  }
}

This overload doesn't specify the dialog type; however, you are forced to register the Window-ViewModel mappings in a class implementing IWindowViewModelMappings.

What Now?

I would like to hear your thoughts about the idea. Perhaps you have a better solution? Don't be afraid, leave a comment...

History

  • 5 October 2010: Code update.
    • Updated source according to comments by d302241.
  • 4 April 2010: Code update.
    • Updated source according to comments by Michael Sync.
    • Converted to .NET 4.
  • 18 June 2009: Code update.
    • Code no longer throws exception in Designer mode.
    • Fixed wrong interface summary.
  • 2 June 2009: Code update.
    • Added the ShowOpenFileDialog method to IDialogService.
    • Implemented a service locator instead of keeping DialogService as a Singleton.
  • 27 May 2009: Article update.
    • Updated introduction after comments from William E. Kempf.
  • 25 May 2009: Initial version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

disore
Software Developer
Sweden Sweden
Got my first computer in the 90's and loved it even though it sounded like a coffeemaker.
 
Now getting paid for designing cool WPF applications, and drinks the coffee instead of listening to it being made.

Comments and Discussions

 
QuestionOpenFileDialog Testing - How to set filename? PinmemberAfonso Gomes16-Jun-14 1:22 
AnswerRe: OpenFileDialog Testing - How to set filename? Pinmemberdisore16-Jun-14 1:49 
GeneralRe: OpenFileDialog Testing - How to set filename? PinmemberAfonso Gomes17-Jun-14 3:47 
GeneralRe: OpenFileDialog Testing - How to set filename? Pinmemberdisore17-Jun-14 20:22 
GeneralRe: OpenFileDialog Testing - How to set filename? PinmemberAfonso Gomes17-Jun-14 23:01 
QuestionShowMessageBox in contructor of ViewModel PinprofessionalPattern Master28-Apr-14 20:26 
AnswerRe: ShowMessageBox in contructor of ViewModel Pinmemberdisore28-Apr-14 20:43 
Question5 PinmemberKevin Marois29-Dec-13 10:03 
AnswerRe: 5 Pinmemberdisore29-Dec-13 10:36 
QuestionWhat if I need the reference to a window open ? PinmemberFabrizio Stellato30-Oct-13 5:56 
AnswerRe: What if I need the reference to a window open ? Pinmemberdisore30-Oct-13 12:01 
QuestionExample for Folder brwser dialog in MVVM Pinmembersuderson16-Oct-13 2:04 
AnswerRe: Example for Folder brwser dialog in MVVM Pinmemberdisore16-Oct-13 2:27 
QuestionWhere to put the DialogService Pinmemberxxpatanaxx26-Jul-13 11:21 
AnswerRe: Where to put the DialogService Pinmemberdisore28-Jul-13 9:46 
GeneralMy vote of 4 Pinmemberdieshang24-Jul-13 4:51 
GeneralRe: My vote of 4 Pinmemberdisore25-Jul-13 10:33 
GeneralMy vote of 5 PinmemberMember 1016643421-Jul-13 21:23 
GeneralRe: My vote of 5 Pinmemberdisore25-Jul-13 10:34 
QuestionHow do I close a dialog window from the viewmodel PinmemberMember 85138086-Jun-13 21:26 
AnswerRe: How do I close a dialog window from the viewmodel Pinmemberdisore8-Jun-13 11:42 
GeneralRe: How do I close a dialog window from the viewmodel PinmemberMember 85138089-Jun-13 18:47 
QuestionFindOwnerWindow function: owner view never registered PinmemberMember 990347113-Mar-13 0:03 
AnswerRe: FindOwnerWindow function: owner view never registered Pinmemberdisore13-Mar-13 5:00 
GeneralRe: FindOwnerWindow function: owner view never registered PinmemberMember 990347113-Mar-13 22:32 
GeneralMy vote of 5 PinmemberSergey A Alekseev5-Mar-13 19:35 
GeneralRe: My vote of 5 Pinmemberdisore5-Mar-13 19:48 
QuestionRequire your help on Modal Dialog PinmemberMember 93903114-Mar-13 23:42 
AnswerRe: Require your help on Modal Dialog Pinmemberdisore5-Mar-13 11:33 
GeneralRe: Require your help on Modal Dialog PinmemberMember 93903115-Mar-13 19:31 
GeneralRe: Require your help on Modal Dialog Pinmemberdisore5-Mar-13 19:57 
GeneralRe: Require your help on Modal Dialog PinmemberMember 93903115-Mar-13 20:13 
GeneralRe: Require your help on Modal Dialog Pinmemberdisore5-Mar-13 20:21 
GeneralRe: Require your help on Modal Dialog PinmemberMember 93903115-Mar-13 20:23 
GeneralRe: Require your help on Modal Dialog Pinmemberdisore5-Mar-13 20:27 
GeneralRe: Require your help on Modal Dialog PinmemberMember 93903115-Mar-13 20:59 
GeneralMy vote of 1 Pinmemberabdurahman ibn hattab24-Jan-13 10:03 
GeneralMy vote of 5 PinmemberChad Strawinski18-Jan-13 6:35 
QuestionPretty interesting! PinmemberCandyBeat13-Dec-12 3:58 
AnswerRe: Pretty interesting! Pinmemberdisore13-Dec-12 11:08 
GeneralRe: Pretty interesting! PinmemberCandyBeat14-Dec-12 22:55 
Hi! I see your point and I think you're right. Connecting the View and the ViewModel should be made by a third component in the relationship.
 
I saw in your simple App that you are using the Service Locator pattern. Do you think you could build a sample using MEF? Would it be too complex? About the Cinch Framework, I think I will make the step, but I'm afraid of using a Framework that is somewhat unofficial or unsupported. Anyways, I will look into it.
 
Regarding the need of using Windows from the ViewModel this is my point of view:
You are in a Window (main) and the user chooses to edit some type of entity, for example, the user wants to Options/Preferences… Then in an abstract way of seeing this, the user want to temporarily change the context (the focus of his actions) and the unique reason for it is to modify data related with preferences. This is: the user wants to edit some Preferences ítem and when it's done, he will go back to where the actions started.
 
In fact, I see the workflow like calling an external program that modifies the required information and returns. This is valid only for Dialogs (Modal Windows). So the ViewModel may start up the action just with a method like:
 
var returnValue = DialogService.Edit(preferences);
 
The DialogService then should execute the necessary actions to edit that entity. Of course it would have some overloads so the developer would choose what kind of "Edit" he will be using (over the and a default one).
 
Please, tell me your opinion. And THANKS a lot for your comment!
GeneralRe: Pretty interesting! Pinmemberdisore17-Dec-12 8:21 
GeneralMy vote of 5 Pinmemberkarl-barkmann5-Dec-12 15:34 
GeneralRe: My vote of 5 Pinmemberdisore5-Dec-12 19:55 
QuestionWhat Is The Service For??? PinmemberKevin Marois7-Nov-12 5:31 
AnswerRe: What Is The Service For??? Pinmemberdisore7-Nov-12 10:18 
GeneralRe: What Is The Service For??? PinmemberKevin Marois7-Nov-12 10:34 
GeneralRe: What Is The Service For??? Pinmemberdisore7-Nov-12 11:45 
GeneralRe: What Is The Service For??? PinmemberKevin Marois7-Nov-12 12:02 
GeneralRe: What Is The Service For??? Pinmemberdisore7-Nov-12 12:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140902.1 | Last Updated 5 Oct 2010
Article Copyright 2009 by disore
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid