Reputation: 20279
Commanding is mainly used to have a clear separation between the ViewModel and the user interface. What is the difference between event subscription and commanding? Consider the following example:
public App ()
{
Button button = new Button
{
Text = "Press me",
};
button.Clicked += Button_Clicked;
// The root page of your application
MainPage = new ContentPage {
Content = new StackLayout {
VerticalOptions = LayoutOptions.Center,
Children = {
button,
}
}
};
}
private void Button_Clicked(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine("Pressed!");
}
VS.
public App ()
{
Button button = new Button
{
Text = "Press me",
};
button.Command = new Command(() => System.Diagnostics.Debug.WriteLine("Pressed!"));
// The root page of your application
MainPage = new ContentPage {
Content = new StackLayout {
VerticalOptions = LayoutOptions.Center,
Children = {
button,
}
}
};
}
Regarding memory management one should unsubscribe from the event. Is this also valid for commanding? Where should one subscribe/unsubscribe to/from the event? In OnAppearing()
and OnDisappearing()
?
Upvotes: 4
Views: 2927
Reputation: 3228
Typically, your commands would exist as properties of a View Model (as called for in the MVVM design pattern). They encapsulate the concept of performing isolated actions upon the View Model, or in transitioning from one View Model to another - such as during navigation activities. This decouples the action from your visual interface, which enables unit testing of that code. Also, because the command is wired up in MVM via Bindings, you don't need to worry about unsubscribing the events.
In short form:
This is more like what your second example should look like:
public class ViewModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private string _text;
public string Text {
get { return _text; }
private set {
if (_text != value ) {
_text = value;
OnPropertyChanged("Text");
}
}
}
public ICommand Cmd { get; private set; }
public ViewModel() {
Text = "Press me";
Cmd = new Command(() => {
System.Diagnostics.Debug.WriteLine("Pressed!");
Text = "Thanks!";
});
}
private void OnPropertyChanged(string propertyName) {
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
//.....
public App ()
{
Button button = new Button();
button.BindingContext = new ViewModel();
button.SetBinding(Button.TextProperty, "Text");
button.SetBinding(Button.CommandProperty, "Cmd");
// The root page of your application
MainPage = new ContentPage {
Content = new StackLayout {
VerticalOptions = LayoutOptions.Center,
Children = {
button,
}
}
};
}
Note that the ViewModel class contains zero code that deals with visual controls, and thus can be very easily unit tested. Also, the code in the App class that handles the UI is now MUCH more simple.
Normally I would recommend using XAML markup and not code for this though. The Binding syntax is much easier to follow in XAML in my opinion.
Upvotes: 6