0

I spent most of today trying to make sense of the MANY different approaches to closing a dialog in WPF/MVVM. Most answers focus on simple dialogs - like a Yes/No confirmation dialog. However, no one seems to describe a more complicated case of a dialog that actually performs some actions, which have to be committed in a transactional way: all-or-nothing.

There is an OK button, clicking which invokes a bound command on the ViewModel. All is fine.

Now, I want to close the window if the command succeeds, but I don't want to close it, if the command fails.

After hours of research I came to the conclusion that apparently no one in the world has ever had a similar problem to solve :|

The solution that I invented, but have not implemented yet is as follows:

  1. I would have a ConditionalCloseWindow command, which takes the window as a parameter and, well, closes the window.

  2. The ConditionalCloseWindow command would have an attached property:

    public static readonly DependencyProperty Condition =
        DependencyProperty.RegisterAttached("Condition", typeof(ICommand), ... snip
    
  3. Executing the ConditionalCloseWindow command would first cause the execution of the Condition command. Only on successful execution of the Condition command would the ConditionalCloseWindow actually perform the Close().

What do you think of such solution? Is it totally invalid? Or maybe it is an accepted pattern, that I have not succeeded to discover through my research?

Adi Lester
  • 24,731
  • 12
  • 95
  • 110
Jakub Kaleta
  • 1,740
  • 1
  • 18
  • 25

3 Answers3

1

One way would set up a Closing event handler in ViewModel, such as:

<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
    <command:EventToCommand Command="{Binding WindowClosing}" />
</i:EventTrigger>
</i:Interaction.Triggers>

in ViewModel:

public ICommand WindowClosing
{
    get
    {
        return _windowClosing ?? _windowClosing = new RelayCommand<CancelEventArgs>(
            (args) =>{
                   if(somethingDoesNotMakeSense) 
                       args.Cancel = true;
                });
    }
}

though this can get a little messy.

Another one I thought up;

            <i:Interaction.Triggers>
            <i:EventTrigger EventName="Click">
                <commandCall Command="ButtonClicked" />
                <commmandCall Command="CloseWindow" Parameter="{Binding VIewModelCanWeClose}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>

CloseWindow should be command, implemented in Codebehind, which will get in parameter "should we close or not" and call Close() based on it.

Erti-Chris Eelmaa
  • 25,338
  • 6
  • 61
  • 78
0

There are many ways to solve your problem. My first suggestion is, that your dialogs ViewModel has a property of type action. Your dialog set that property to a action that closes the dialog. In your command you can invoke that action and your dialog will close.

Andre
  • 1,044
  • 1
  • 11
  • 23
0

There are various "Form" controls out there that allow you to orchestrate things i.e. support validation, cancel/ok logic, close, etc.

You can use IEditableObject on your "model" to handle the commit of changes in a transactional way.

Colin Smith
  • 12,375
  • 4
  • 39
  • 47