ViewBag and ViewData ViewModel Properties


ViewBag is a ViewModel property and is one of the main advantages of Fluent MVVM.

Important: ViewBag property isn’t mandatory, and you can choose when to use it and when not..

ViewBag greatly accelerates the development and allow us to focus on the business forgetting repeating task such as defining full properties and implement INotifyPropertyChanged.
S
This is a definition comparation with and without ViewBag.

Initial Form

With ViewBag> property just need the initialize ViewBag property. Without ViewBag> it is necessary write a full property and to implement and to call INotifyPropertyChanged interface>.



Pros and Cons



Pros


  • It isn’t necessary to define properties we will just have to initialize them online.

  • It isn’t necessary implement INotifyPropertyChanged interface or call PropertyChanged event in sets methods.

  • Accelerates development and makes it very much fun by removing repetitive boring tasks and creation of properties.

  • The code is greatly reduced.

  • The code is more readable.

  • We can choose with properties are ViewBag or ViewData and which ones are not. We can mix them without a problem.

Cons


  • ViewBagcode> is a dynamic property, so than we lost the intellense. If we use a property very much in a ViewModel, this property isn’t candidate to be ViewBag property and the good solution is created a standard property. This problem not exists in the more cases, because in the ViewModels classes the vast majority of properties are used for move values to the Views. If we are very lazy, we can fix it with a casting.

  • For non-string properties in Two-Away binding may have problems with special string formats. We will be examples later.



Example



We will star preparing the project (view QuickStart section, to initialize). Install Nuget, create folders, add IoC configuration and AutoViewModel config.


We will centrate in View and ViewModel classes implementation.

PM installation


We will build a simple example of filter data. We have added a Mock Repository for work data.



Add Code To ViewModel Class




using FluentMVVMExamplesDesc.ViewBag.Data;
using MoralesLarios.FluentMVVM;
using MoralesLarios.FluentMVVM.Infrastructure;
using System;

namespace FluentMVVMExamplesDesc.ViewBag.ViewModels
{
    public class MainViewModel : ViewModelBase
    {
        private readonly IMockAlbumRepository _mockAlbumRepository;

        public MainViewModel(IMockAlbumRepository mockAlbumRepository)
        {
            _mockAlbumRepository = mockAlbumRepository;

            InitialViewBag();
        }

        private void InitialViewBag()
        {
            ViewBag.PrincipalData = _mockAlbumRepository.GetData();

            ViewBag.ArtistNameFilter    = string.Empty;
            ViewBag.AlbumNameFilter     = string.Empty;
            ViewBag.GenreFilter         = string.Empty;
            ViewBag.ReleaseInitFilter   = DateTime.Today.AddYears(-50);
            ViewBag.ReleaseEndFilter    = DateTime.Today;
            ViewBag.NumCopiesInitFilter = 0m;
            ViewBag.NumCopiesEndFilter  = 100000000m;
        }

        public SimpleRelayCommand FilterCommand => new SimpleRelayCommand(FilterExecuted);

        private void FilterExecuted()
        {
            var filter = new AlbumFilterInfo
            {
                ArtistName    = ViewBag.ArtistNameFilter,
                AlbumName     = ViewBag.AlbumNameFilter,
                Genre         = ViewBag.GenreFilter,
                ReleaseInit   = ViewBag.ReleaseInitFilter,
                ReleaseEnd    = ViewBag.ReleaseEndFilter,
                NumCopiesInit = ViewBag.NumCopiesInitFilter,
                NumCopiesEnd  = ViewBag.NumCopiesEndFilter
            };

            ViewBag.PrincipalData = _mockAlbumRepository.Filter(filter);
        }
    }
}

Very little code and very readable.

Injected MockRepository.

private readonly IMockAlbumRepository _mockAlbumRepository;

public MainViewModel(IMockAlbumRepository mockAlbumRepository)
{
    _mockAlbumRepository = mockAlbumRepository;

    InitialViewBag();
}

Necessary for data control.

Add InitialViewBag method

private void InitialViewBag()
{
    ViewBag.PrincipalData = _mockAlbumRepository.GetData();

    ViewBag.ArtistNameFilter    = string.Empty;
    ViewBag.AlbumNameFilter     = string.Empty;
    ViewBag.GenreFilter         = string.Empty;
    ViewBag.ReleaseInitFilter   = DateTime.Today.AddYears(-50);
    ViewBag.ReleaseEndFilter    = DateTime.Today;
    ViewBag.NumCopiesInitFilter = 0m;
    ViewBag.NumCopiesEndFilter  = 100000000m;
}

We will instantiated the ViewBag in a private method because is more readeable, and is more easy recall.

Add FilterCommand

public SimpleRelayCommand FilterCommand => new SimpleRelayCommand(FilterExecuted);

private void FilterExecuted()
{
    var filter = new AlbumFilterInfo
    {
        ArtistName    = ViewBag.ArtistNameFilter,
        AlbumName     = ViewBag.AlbumNameFilter,
        Genre         = ViewBag.GenreFilter,
        ReleaseInit   = ViewBag.ReleaseInitFilter,
        ReleaseEnd    = ViewBag.ReleaseEndFilter,
        NumCopiesInit = ViewBag.NumCopiesInitFilter,
        NumCopiesEnd  = ViewBag.NumCopiesEndFilter
    };

    ViewBag.PrincipalData = _mockAlbumRepository.Filter(filter);
}

We have used a helper filter class AlbumFilterInfo for don't add 7 parameters to Filter Repository method.


Add Code To View Class


In the View class we have added code for ItemsSorce ListBox property, for Bindings filters controls and the button filter command.


This is a summary of changes.

<ListBox ItemsSource="{Binding ViewBag.PrincipalData}"/>

<TextBox Text="{Binding ViewBag.ArtistNameFilter, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"/>
<TextBox Text="{Binding ViewBag.AlbumNameFilter, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
<TextBox Text="{Binding ViewBag.GenreFilter    , Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
<DatePicker SelectedDate="{Binding ViewBag.ReleaseInitFilter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, StringFormat=dd/MM/yyyy}" />
<DatePicker SelectedDate="{Binding ViewBag.ReleaseEndFilter , Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, StringFormat=dd/MM/yyyy}" />
<TextBox Text="{Binding ViewBag.NumCopiesInitFilter, Mode=TwoWay, UpdateSourceTrigger=LostFocus, StringFormat=n}" />
<TextBox Text="{Binding ViewBag.NumCopiesEndFilter , Mode=TwoWay, UpdateSourceTrigger=LostFocus, StringFormat=n}" />

<Button Command="{Binding FilterCommand}"/>

You have available all code in the finish of the page, and you will see too in the next video

All process in video.





SetViewBagValue



Exists other ViewBag instantiation way through SetViewBagValue method. These are its signatures:


public void SetViewBagValue<T>(string propertyName, T value)
public void SetViewBagValue(Type type, string propertyName, object value)

Has two versions, generic a non-generic.

The main task is instantiating ViewBag properties more specifically. In classical ViewBag instantiation the type of ViewBag property is inferred from variable value but in more cases the type inferred isn’t what we wanted it. SetViewBagValue is very practical for ViewBag Nullables types properties builder.



SetViewBagNullValue


SetViewBagNullValue is a ViewModelBase method very similar to SetViewBagValue. Your difference is that SetViewBagNullValue only instance a ViewBag property with nullcode> value. We could think that this code is more comun.

ViewBag.MyProperty = null;

This code throws a new ArgumentNullException, because Fluent MVVM engine can’t infer the property type.

ArgumentNullException

This is the correct null initialization


//ViewBag.MyProperty = null;

SetViewBagNullValue<string>("MyProperty");
// or
SetViewBagNullValue(typeof(string), "MyProperty");

In this case, we have chosen a string type, we could have chosen any other type that admit null values.
For tests this characteristic let’s add a new control filter. The new control will be a checkbox and will filter the field HaveIt with this rule.
  • Null value .- Show all values
  • True value.- Show all true values
  • False value.- Show all false values

Since it is not possible to put back to put to null a ckeckbox value, will add a button to reset current filters.

Add HaveItFilter ViewBag property and ResetCommand to our ViewModel.



private void InitialViewBag()
        {
            ViewBag.PrincipalData = _mockAlbumRepository.GetData();

            ViewBag.ArtistNameFilter    = string.Empty;
            ViewBag.AlbumNameFilter     = string.Empty;
            ViewBag.GenreFilter         = string.Empty;
            ViewBag.ReleaseInitFilter   = DateTime.Today.AddYears(-50);
            ViewBag.ReleaseEndFilter    = DateTime.Today;
            ViewBag.NumCopiesInitFilter = 0m;
            ViewBag.NumCopiesEndFilter  = 100000000m;

            SetViewBagNullValue<bool?>("HaveItFilter");
        }

FilterCommand

public SimpleRelayCommand ResetCommand => new SimpleRelayCommand(() => InitialViewBag());

Important: We have omited CanExecute method, because it isn't important for this section. View EaseyRelayCommands for more info.

Add Checkbox filter and reset button to View.

<CheckBox IsChecked="{Binding ViewBag.HaveItFilter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ... />
<Button Command="{Binding ResetCommand}" ... />

Result.

Window with new checkbox filter

Checkbox has green background, whit its value is null.


All process in video.



ViewBagPropertyChanged Event

ViewBagPropertyChanged event, is the instrument responsible for reporting ViewBag properties changed. This event allows to makes changes or run actions when our ViewBag properties are modified. In a normal MVVM implementation this actions would be carried in the setters full properties after value assignation.
Example Traditional MVVM.


private string _myProperty;

        public string MyProperty
        {
            get { return _myProperty; }
            set
            {
                _myProperty = value;

                /// MyActions
            }
        }
        

Example with ViewBag properties.


ViewBagPropertyChanged += (sender, e) =>
        {
            if(e.PropertyName == "MyProperty")
            {
                /// My Actions
            }
        };
        

For our example, Add ViewBagPropertyChanged event in a InitialBag methood.


private void InitialViewBag()
{
    ViewBag.PrincipalData = _mockAlbumRepository.GetData();

    ViewBag.ArtistNameFilter    = string.Empty;
    ViewBag.AlbumNameFilter     = string.Empty;
    ViewBag.GenreFilter         = string.Empty;
    ViewBag.ReleaseInitFilter   = DateTime.Today.AddYears(-50);
    ViewBag.ReleaseEndFilter    = DateTime.Today;
    ViewBag.NumCopiesInitFilter = 0m;
    ViewBag.NumCopiesEndFilter  = 100000000m;

    SetViewBagNullValue<bool?>("HaveItFilter");

    ViewBagPropertyChanged += (sender, e) =>
    {
        if(e.PropertyName != "PrincipalData") 
        {
            FilterExecuted();
        }
    };
}


All in video.






Download Examples Code










No hay comentarios :

Publicar un comentario