简体   繁体   中英

Questions regarding WPF commands

I have a few questions regarding WPF commands.

  1. Where should I put confirmation dialogs? Should I show them right inside the command callback function? What if in some areas in the application I don't want a command to show a confirmation?

  2. If I have a user control that shows items that can be deleted. Should the command be in the application's view model, and I use it for the item deletion, or should the user control itself also have a command that in turn calls the view model's function? (Note: the application view model is the only one having the information needed to do this operation)

  3. How can I pass data within a command? I am using mostly DelegateCommand , and upon firing a command for a grid item, I'd like to pass the selected item, otherwise the application's main view model would have to find the grid and figure out its selection which will hardcode the command to the grid and not make it reusable.

A bit of this is opinion and style . . . Here's my approach:

Question 1:

I have a utility class that handles any confirmation, and I use the lightweight messaging in MVVM Light to handle communication between the view, the confirmation, and the viewmodel.

Edit: A bit more information on point 1

From within my Command, I will send a message along the lines of "ConfirmDeletionMessage", which is then picked up by my dialog utility class. The dialog utility class displays the appropriate message to the user, and checks the results. Based on the results, it will either broadcast a "DeletionConfirmedMessage" or "DeletionCanceledMessage," which is then handled by the ViewModel to either complete or cancel the delete.

There is some risk involved if you have multiple subscribers to this message, as you won't know what order they're going to be handled, but if you have strict management on message consumers, or ensure that they are able to run in a random order, this approach works pretty well, and it separates your View and Model code in a testable fashion.

Question 2:

This is a tough one, and it is going to depend on your overall application. I'm personally a fan of putting it in the item's viewmodel. That way, you don't have to worry about your third question as much. Instead, the delete action simply works on the item you're dealing with. However , if you have to act on data outside of your list item (like removing it from the list), it makes more sense for the command to be on the parent viewmodel.

Question 3:

Use the CommandParameter property. You can bind this to whatever you want.

EDIT to Answer #2

Mark Green (who commented below) got me thinking. I originally adopted this approach for WP7, and it absolutely suited what I needed to do. However, there are other ways of handling this that should absolutely be considered. Another option is a "confirmation class" that can be used by your viewmodel. If you are using an IoC kernel, this becomes easy to do with constructor / property injection. Alternatively, if you have other methods of getting the class, do so, but do it in a way that you can mock out in testing. It might look something like this:

public class ExampleViewmodel : ViewModel
{
      private IConfirmDialogManager _dialogManager;
      public ExampleViewmodel(IConfirmDialogManager dialog)
      {
            _dialogManager = dialog;
      }

      // ... code happens ...
      private void DeleteCommand()
      {
             bool result = _dialogManager.Confirm("Are you sure you want to delete?");
      }
}

With an IConfirmDialogManager interface that looks like this:

public interface IConfirmDialogManager
{
      bool Confirm(string message);
}

Which you would then implement appropriately.

Where should I put confirmation dialogs? Should I show them right inside the command callback function? What if in some areas in the application I don't want a command to show a confirmation?

Confirmation dialogs and show message dialogs are views. Your VM should have a way of notifying your view that it wants to display something or ask something, then the view should decide how to display it (status bar, window, pop-up, voice message, ...)

If I have a user control that shows items that can be deleted. Should the command be in the application's view model, and I use it for the item deletion, or should the user control itself also have a command that in turn calls the view model's function? (Note: the application view model is the only one having the information needed to do this operation)

The items control should raise a delete command. The VM should handle the command and decide what to do (the VM should have the list of the selected items and the view should be binding to that list).

How can I pass data within a command? I am using mostly DelegateCommand, and upon firing a command for a grid item, I'd like to pass the selected item, otherwise the application's main view model would have to find the grid and figure out its selection which will hardcode the command to the grid and not make it reusable.

Commands can have parameters (eg RoutedUICommand). The command binding can specify a binding expression for the parameter. However, the correct approach is for the VM to be the source of the selection with a two way binding between the view's selection and the VM's.

  1. simply use a dialogservice in your viewmodel
  2. it depends but nevertheless the object/viewmodel where the command is located can easily reached with RelativeSource binding
  3. CommandParameter is one way. in fact you use mvvm all information you need should be bind to your viewmodel. so if you have a command and you need the selecteditem from a listview, you can bind it to the viewmodel and dont need to set this as commandparameter

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM