7

I'm working on a view model for a view that presents a dialog with export options. The user selects options then clicks Export. When the view model completes the Export, the calling view model receives notification.

I'm curious which is the better practice for implementing the notification: a traditional event or an Action callback that gets passed in when the dialog is opened.

Traditional Event

public class ExportDialogViewModel : ViewModelBase
{
    private readonly ICommand _exportCommand;
    private readonly ICommand _cancelCommand;

    public event EventHandler Finished;

    public ICommand ExportCommand
    {
        get { return _exportCommand; }
    } 

    public ICommand CancelCommand
    {
        get { return _cancelCommand; }
    }

    public ExportDialogViewModel()
    {
        _exportCommand = new RelayCommand(Export);
        _cancelCommand = new RelayCommand(Cancel);
    }

    public void Initialize()
    {
        //set the initial conditions
    }

    public void Export()
    {
        //perform export
        OnFinished();
    }

    public void Cancel()
    {
        OnFinished();
    }

    private void OnFinished()
    {
        if (Finished != null) Finished(this, EventArgs.Empty);
    }
}

Callback

public class ExportDialogViewModel2 : ViewModelBase
{
    private readonly ICommand _exportCommand;
    private readonly ICommand _cancelCommand;

    private Action _callback;

    public ICommand ExportCommand
    {
        get { return _exportCommand; }
    }

    public ICommand CancelCommand
    {
        get { return _cancelCommand; }
    }

    public ExportDialogViewModel2()
    {
        _exportCommand = new RelayCommand(Export);
        _cancelCommand = new RelayCommand(Cancel);
    }

    public void Initialize(Action callback)
    {
        _callback = callback;
        //set the initial conditions
    }

    public void Export()
    {
        //perform export
        _callback();
    }

    public void Cancel()
    {
        _callback();
    }
}

My initial thoughts are that the traditional event is a little more flexible: it allows more than one subscriber to be notified, and it also allows zero subscribers to be notified. The callback, on the other hand, enforces a particular way of interacting with the dialog--the callback must be passed in during initialization. The callback is also simpler to implement and use, though perhaps less familiar than events.

Which of the two notification patterns do you recommend and why?

1
  • Using Action you can have either multiple or zero handlers, by using either the Composite (or perhaps Chain of Responsibility), or the Null Object patterns respectively. It's a little more work, though, so I'd suggest using events if you think either is a likely scenario (but relax because if you're wrong you do have a fallback mechanism to achieve what you want).
    – Jules
    Jan 11, 2015 at 14:53

1 Answer 1

7

You basically answered your own question in your last paragraph. Each option behaves similarly to a certain degree, is programmed differently, and presents trade-offs in terms of flexibility and simplicity.

With Actions, you can implement them so that you don't require any sort of initialization step. They can be passed into a function, and triggered under certain conditions within the method called. You can also use actions to behave exactly like an event, by assigning an action to a property and triggering the action when needed. As you've already stated though, the Action will only allow you to notify one single handler. Under some circumstances, this may be useful if your intention is to limit notification to only a single handler. I can't think of many circumstances off the top of my head where this would really be worth the effort so to speak.

Events are beautiful things. I remember writing my first Event driven code in Delphi many years ago, and it occurred to me at the time (and with my worldly 6-months of experience) that there really wasn't much of a reason not to make all application code event-driven. when I eventually cam across the MVC pattern a few years later, I wasn't surprised to see that it was essentially an event-driven pattern. There is a great elegance and simplicity to simply connecting a whole bunch of individual event handlers to a simple notifier, and having all of those handlers simply do their own little thing, rather than needing to write a big long method full of edge-case logic do do the same thing. Even better is the ability to replace or add to functionality simply by changing or adding to the list of handlers registered to a particular event.

For these reasons I'd be tempted to go out on a limb and say that events are better to a degree, but as with all things there is a time and place for everything, and sometimes an action will serve just as well, though perhaps not as any reasonable replacement for an event.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.