Why do RelayCommands typically use lazy initialization?
Asked Answered
A

1

20

When using Josh Smith's RelayCommand, most of the examples I've seen use lazy initialization such as:

public class ViewModel
{
    private ICommand myCommand;

    public ICommand MyCommand
    {
        get
        {
            if (myCommand == null)
            {
                myCommand = new RelayCommand(p => DoSomething() );
            }

            return myCommand;
        }
    }
    // ... stuff ...

}

Rather than creating the RelayCommand in the constructor, like this:

public class ViewModel
{
    public ViewModel()
    {
            MyCommand = new RelayCommand(p => DoSomething());
    }

    public ICommand MyCommand
    {
        get;
        private set;

    }

    // ... stuff ...
}

What's the benefit of using lazy initialization here? It will have to call the get property when setting up the binding, so I can't seen a reason to use this method over settings things up in the constructor.

Am I missing something here?

Altogether answered 22/9, 2010 at 13:53 Comment(1)
You are right. Lazy initialization of RoutedCommands doesn't make any sense because they are very lightweight and they are loaded anyway as soon as the View binds to it.Portwine
F
15

Actually, WPF and Silverlight will get the relay command just once per binding, so you don't really need to store a backing field at all:

public ICommand MyCommand
{
    get
    {
        return new RelayCommand(p => DoSomething());
    }
}

So while there's nothing wrong with creating it in the .ctor as you suggest, there's very little reason to.

Figment answered 22/9, 2010 at 13:55 Comment(6)
"WPF and Silverlight will get the relay command just once per binding" -- I know in practice this is true. But, given that the documentation does not promise this behavior, is it really all that wise to create a new object each time the property value is retrieved? What happens that day that Microsoft, for whatever reason, decides it makes more sense to let your model object keep the command object reference instead of caching it somewhere, and they just get the value from the property every time they need it?Cwmbran
@Peter Duniho: Not only Microsoft; my view model calls its commands (and CanExecute()) directly from its own methods all the time. So, no, it would be unwise to create a new instance every time.Keffiyeh
@BoltClock: good point. I will be more explicit about the scenarios in the other postCwmbran
Upvoting the answer anyway for the main point - that binding happens right away, exactly once (per view + view model), obviating the need for lazy initialization. You should still use a backing field if your version of C# does not support it (this being an older Q&A); in C# 6 and later getter-only properties can be auto-implemented.Keffiyeh
@Peter Duniho: So I realized why I hadn't been making use of field/property initializers - because my commands themselves also call view model instance methods. Granted, I could just move these initializations to the constructor instead, though I'm not sure it'll make much of a difference. I've chosen not to refactor at all.Keffiyeh
Thats a horrible solution. Your view can bind to the same command multiple times (maybee one button in main menu and the other in context menu). If you create multiple instances for the same command its possible harder for debugging.Crackdown

© 2022 - 2024 — McMap. All rights reserved.