0
votes

I'm not sure if I'm thinking about this in the correct way. I have a list of objects, and I would like the user to be able to edit and view the properties of a specified object. My initial thought is great, I'll pop up a dialog that has textboxes and let the user edit to their heart's content until they press either Ok or Cancel.

I'm on UWP, and using Prism for all of my MVVM needs. It's taken me a while, but I understand creating Views and their associated ViewModels, commands, etc. So far, I think I've done a good job keeping the view logic and business logic separated.

I've searched, but haven't found how to show a dialog in a way that follows MVVM principles. The two things that seem to be coming up the most are to use Interaction requests (which don't appear to exist using Prism on UWP), and creating a custom Content Dialog and showing it by calling ShowAsync in a method in the parent view's associated ViewModel (which seems to be counter to MVVM principles).

So, how do I either show a dialog that is defined using XAML and has an associated ViewModel (preferable since it is similar to what I'm familiar with), or another way I can tackle this problem?

1

1 Answers

0
votes

Using MVVM the proper place for opening a dialog is in the ViewModel.

Usually I do something like this in your scenario:

Create an interface for showing dialogs:

public interface IWindowService
{
    void OpenViewModelInWindow(ViewModelBase vm, string title, bool resizeable = true);
    void CloseViewModelInWindow(ViewModelBase vm);
}

Implement this interface in UI layer:

public class WindowService : IWindowService
{
    private List<Window> _windows = new List<Window>();

    public void OpenViewModelInWindow(ViewModelBase vm, string title, bool resizeable = true)
    {
        var window = new Window
        {
            Title = title,
            Content = vm,
            Owner = Application.Current.MainWindow,
            WindowStartupLocation = WindowStartupLocation.CenterOwner,
            ShowInTaskbar = false,
            SizeToContent = SizeToContent.WidthAndHeight,
            ResizeMode = resizeable ? ResizeMode.CanResize : ResizeMode.NoResize
        };
        _windows.Add(window);
        window.ShowDialog();
    }

    public void CloseViewModelInWindow(ViewModelBase vm)
    {
        _windows.Single(w => w.Content == vm).Close();
    }
}

In your App.xaml you need to define DataTemplates so that when you set the Content property of the window the corresponding View created in the window.

<DataTemplate DataType="{x:Type viewModel:AViewModel}">
    <views:AUserControl />
</DataTemplate>

Then you can use the IWindowService from the ViewModel, you should inject it by constructor injection.

This way you are not referencing framework specific classes directly from the ViewModel. ViewModel has a reference only to an IWindowService. This has a benefit also when you want ot write unit test for a viewmodel. You can mock this service so that when the unit test is running it should not open a dialog.