MVVMbasics Features

↑ back to the MVVMbasics main page

Data Binding

  • Attribute-based bindable property declaration for automatic INotifyPropertyChanged implementation:
    [MvvmBindable]
    public bool IsEnabled { get; set; }
    
  • Shortest possible set-up of bindable properties implementing INotifyPropertyChanged without using attributes:
    private bool _isEnabled;
    public bool IsEnabled
    {
    	get => _isEnabled;
    	set => Set(ref _isEnabled, value);
    }
    
  • Calling additional methods after bindable properties are updated, but only if old and new values are unequal:
    private bool _isEnabled;
    public bool IsEnabled
    {
    	get => _isEnabled;
    	set => Set(SomeCondition, ref _isEnabled, value, SomeMethod);
    }
    
    private bool SomeCondition()
    {
    	// This method is only called if old and new value of the IsEnabled property differ. Moreover, it is
    	// called before the IsEnabled property is updated to its new value, allowing to abort this property
    	// update by returning FALSE.
    }
    
    private void SomeMethod()
    {
    	// This method is only called if old and new value of the IsEnabled property differ. Moreover, it is
    	// called after the IsEnabled property is updated to its new value, allowing, e.g., instant updates
    	// of other properties that depend on IsEnabled.
    }
    

Command Binding

  • Easy declaration of delegate commands, with or withour command parameters:
    public BaseCommand ButtonClickedCommand { get; }
    
    public MyViewmodel()
    {
    	ButtonClickedCommand = CreateCommand(ButtonClickedMethod);
    }
    
    private void ButtonClickedMethod(object parameter)
    {
    	// ...
    }
    
  • Declaration and convenient testing of delegate commands that invoke asynchronous methods:
    public BaseCommand ButtonClickedCommand { get; }
    
    public MyViewmodel()
    {
    	ButtonClickedCommand = CreateAsyncCommand(ButtonClickedMethod);
    }
    
    private async Task ButtonClickedMethod()
    {
    	// ...
    }
    
    [TestMethod]
    public async Task TestDoStuff()
    {
    	await ButtonClickedCommand.ExecuteAsync();
    }
    
  • Platform-independent update of commands’ CanExecute properties:
    [MvvmBindable]
    public bool IsEnabled { get; set; }
    
    public MyViewmodel()
    {
    	ButtonClickedCommand = CreateCommand(ButtonClickedMethod, () => IsEnabled);
    }
    
  • Direct Event to Command binding without code-behind event handlers:
    <ListBox SelectionChanged="EventToCommand"
             mvvm:Event.Command="{Binding ListSelectionChangedCommand}"
             mvvm:Event.CommandParameter="{Binding ElementName=SomeControl, Path=SelectedItem}" ... />
    
  • Automatic binding of commands to Viewmodel methods and CanExecute conditions:
    [MvvmCommandAutobinding]
    public sealed class MyViewmodel : BaseViewmodel
    {
    	public BaseCommand ButtonClickCommand { get; set; }
    
    	public Expression<Func<bool>> CanButtonClick => () => SomeCondition == true;
    
    	private void ButtonClick()
    	{
    		// logic goes here...
    	}
    }
    

Tight coupling of Viewmodel and View

  • Easy binding of pages and windows to Viewmodels:
    [MvvmNavigationTarget(typeof(MyViewmodel))]
    public sealed partial class MyPage : BaseView
    {
    	// ...
    }
    
  • Advanced binding of Windows 10 pages to Viewmodels:
    public sealed partial class MyPage : BaseView, IBindableView<MyViewmodel>
    {
    	public MyViewmodel Vm { get; set; }
    
    	// ...
    }
    
  • Reacting to page / window navigation events directly within Viewmodel code:
    public sealed class MyViewmodel : BaseViewmodel
    {
    	public override void OnNavigatedTo(ParameterList uriParameters, ParameterList parameters, ViewState viewState)
    	{
    		// ...
    	}
    
    	public override bool CancelNavigatingFrom(ViewState viewState)
    	{
    		// ...
    	}
    
    	public override void OnNavigatedFrom(ViewState viewState)
    	{
    		// ...
    	}
    }
    
  • Standardization of page / window status through all platforms:
    public override void OnNavigatedTo(ParameterList uriParameters, ParameterList parameters, ViewState viewState)
    {
    	switch (viewState)
    	{
    		case ViewState.Activated:
    			// ...
    			break;
    		case ViewState.Reactivated:
    			// ...
    			break;
    		case ViewState.Shown:
    			// ...
    			break;
    		case ViewState.Awakened:
    			// ...
    			break;
    	}
    }
    
    public override void OnNavigatedFrom(ParameterList uriParameters, ParameterList parameters, ViewState viewState)
    {
    	switch (viewState)
    	{
    		case ViewState.Deactivated:
    			// ...
    			break;
    		case ViewState.Closed:
    			// ...
    			break;
    		case ViewState.Hidden:
    			// ...
    			break;
    		case ViewState.Hibernated:
    			// ...
    			break;
    	}
    }
    

Platform-independent navigation code

  • Global, platform-independent navigator service that allows page / window navigation from within Viewmodel code:
    var navigator = ServiceLocator.Retrieve<INavigatorService>();
    navigator.NavigateTo<AnotherViewmodel>();
    
  • Passing parameters of complex types between pages / windows:
    navigator.NavigateTo<AnotherViewmodel>(new Parameter("search_time", DateTime.Now));
    
    public override void OnNavigatedTo(ParameterList uriParameters, ParameterList parameters, ViewState viewState)
    {
    	DateTime searchTime;
    	parameters.TryGetDateTime("search_time", out searchTime);
    }
    

Global access to business logic through distinguished MVVM Services:

  • Centrally stored platform-independent services:
    [MvvmService]
    public class SampleService : IService
    {
    	// Service methods follow here...
    }
    
  • Common interfaces defining platform-specific services:
    public interface IPlatformspecificService : IService
    {
    	// Signatures of service methods follow here...
    }
    
    [MvvmService]
    public class PlatformspecificService : IPlatformspecificService
    {
    	// Implementations of service methods (as defined in the service interface) follow here...
    }
    
  • Global service container for registering platform-independent and platform-specific services (that can be replaced by any 3rd party IoC container):
    Services.Register<SampleService>();
    Services.Register(new IPlatformspecificService());
    
    public MyViewmodel(SampleService sampleService, IPlatformspecificService platformspecificService)
    {
    	// ...
    }