Skip to content

Latest commit

 

History

History
90 lines (75 loc) · 3.47 KB

File metadata and controls

90 lines (75 loc) · 3.47 KB

UWP Attached ViewModel Behavior Template

Based on the ideas of Sacha Barber: Attached VM Behaviours

The main idea is getting rid of those big viewmodel code files

  • separation of viewmodel properties/commands and the viewmodel logic: logic is separated into viewmodel behaviors
  • a viewmodel can (and should) have many viewmodel behaviors
  • scales very well with number of properties/commands
  • separation of logic into smaller units makes unit testing easier
  • smaller units increases code maintainability

This project incorporates VM behaviors with PRISM, DI (Unity) and RX - and with ease of use.

####Technical details

  • every viewmodel get its own container (child container of main container)
  • viewmodel and behaviors are resolved by DI: use constructor for own DI purposes
  • IDisposable is implemented such that dispose of viewmodel disposes the container and behaviors

####Example code viewmodel: Don't worry about the constructor - it's due to DI and is handled automagically.

[UsedImplicitly]
public class MainPageViewModel : ViewModel<MainPageViewModel>
{
	public MainPageViewModel(Func<MainPageViewModel, ViewModelBehaviorsController<MainPageViewModel>> controllerFactory)
	  : base(controllerFactory)
	{
		ShowTextCommand = Text.Select(str => !string.IsNullOrWhiteSpace(str)).ToReactiveCommand();

		// determistic start of behaviors
		BehaviorsController.Start();
	}

	public ReactiveProperty<string> Text { get; } = new ReactiveProperty<string>();

	public ReactiveCommand ShowTextCommand { get; }
}

####Example code viewmodel behavior: Show a message box with text from Text propery when ShowTextCommand is invoked.

[UsedImplicitly]
public class ShowTextBehavior : ViewModelBehavior<MainPageViewModel>
{
	protected override void OnStart()
	{
		// subscribe to command - add subscription to dispose list
		RegisterDisposable(ViewModel.ShowTextCommand.Subscribe(_ => ShowMessageDialog()));
	}

	private async void ShowMessageDialog()
	{
		// ViewModel: property available on a behavior
		var dialog = new MessageDialog(ViewModel.Text.Value, "The message is");
		await dialog.ShowAsync();
	}
}

####Example code: register viewmodel and behavior with DI container (App.xaml.cs)

protected override void ConfigureContainer()
{
	base.ConfigureContainer(); // must be called to initialize PRISM

    /* ### container configurator:
     * on request of page (PRISM)
     * -> create viewmodel container / child container
     * -> run the container configurator
     * -> resolve viewmodel, viewmodel behaviors and all other registered dependencies
     * -> viewmodel returned to PRISM
     */
    RegisterViewModelContainerConfigurator<MainPageViewModel>(c =>
    {
        c.RegisterViewModelBehavior<ShowTextBehavior>(); // generics guarantee only behaviors for MainPageViewModel can be registered

        // c.ViewModelContainer: reference to the viewmodel container - do custom registrations here
    });
}

####Links

####Notes Code is annotated with attributes for ReSharper - JetBrains.Annotations