Collection of view models

A TreeView -- like a ListBox or any other ItemsControl -- displays a collection of items. Each of the items deserves its own view model. This lets you data bind the contents of the TreeViewItem.

Wrap every item

Produce a collection of view models using Linq or the Select() extension method. The Select() extension method operates on a collection as a whole. It maps every element of the collection into another parallel collection. For example, to wrap every Survey in a SurveyViewModel, you can use this code:

public IEnumerable<SurveyViewModel> Surveys
{
    get
    {
        return _game.Surveys
            .Select(s => SurveyViewModel.Wrap(s, _navigation));
    }
}

The Select method returns a collection containing one view model for every Survey in the data model.

This is equivalent to the "from ... select" Linq syntax:

public IEnumerable<SurveyViewModel> Surveys
{
    get
    {
        return
            from s in _game.Surveys
            select SurveyViewModel.Wrap(s, _navigation);
    }
}

Either way, the method SurveyViewModel.Wrap is called for each Survey in the data model. This method is just a safe way of calling the constructor:

public static Survey
/// <summary>
/// Summary description for Main.
/// </summary>
static void Main(string[] args)
{
  // string variable
  string myString = "myString";

  /* integer 
     variable */
  int myInt = 2;
}
ViewModel Wrap(Survey survey, GameNavigationModel navigation)
{
    if (survey == null)
        return null;
    else
        return new SurveyViewModel(survey, navigation);
}

While the data model contains no nulls, the navigation model may. That's when the safe Wrap method comes in handy.

Retain identity

Update Controls will honor the identity of items in a collection. This is important for retaining selection between updates. If we created a new collection of view models every time, the items that the user had selected before the list changed would no longer be selected afterward.

Update Controls uses the Equals and GetHashCode methods to determine if two items should be treated as identical. These methods of the view model should delegate to the data model.

public override bool Equals(object obj)
{
    if (obj == this)
        return true;
    SurveyViewModel that = obj as SurveyViewModel;
    if (that == null)
        return false;
    return object.Equals(this._survey, that._survey);
}

public override int GetHashCode()
{
    return _survey.GetHashCode();
}

These methods should be implemented for every view model that appears in a collection.