WinRT app guide: Step 5: Adding the model and some helper classes
To read the other steps in the step by step guide for creating a Metr/ WInRT application go here
Sorry for this tiny delay on the blog post, I’ve been in Bulgaria for Telerik’s 10 year anniversary/teambuilding thursday - monday , and the resort we stayed at only had wifi in the bar - and an incredible slow one too! But I’m back now, and back online and back on track! Let’s start adding some more code and get this app working!
Add a class under Common called BindableBase, this class will help us implement INotifyPropertyChangedInterface on our properties in a nice way, using the new CallerMemberNameattributes that removes the magic string we had to use before to notify the property that it had been changed. Read more about the new attributed in this blog post: ‘Stupid’ Question 12: What is this new attribute [CallerMemberName] in C#?
[sourcecode language=“csharp”]
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace Mihsp.Common
{
[Windows.Foundation.Metadata.WebHostHidden]
public abstract class BindableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null)
{
if (object.Equals(storage, value)) return false;
storage = value;
this.OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var eventHandler = this.PropertyChanged;
if (eventHandler != null)
{
eventHandler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
[/sourcecode]
Add three new folders, Repository , Utility and Model.
.
Repository: will help us access the data layer (the model). All the add, remove, update and get methods will be here.
Utility: static helper classes
Model: the model, the blueprint for our data
Add the class StudyActivities to the Model folder, let it inherit from BindableBase. Add the following properties, and use a private field to back them up.
[sourcecode language=“csharp”]
using Mihsp.Common;
using System;
namespace Mihsp.Model
{
public class StudyActivity: BindableBase
{
private string _title = string.Empty;
public string Title
{
get { return this._title; }
set { this.SetProperty(ref this._title, value); }
}
private string \_categoryName = string.Empty;
public string CategoryName
{
get { return this.\_categoryName; }
set { this.SetProperty(ref this.\_categoryName, value); }
}
private string \_comment = string.Empty;
public string Comment
{
get { return this.\_comment; }
set { this.SetProperty(ref this.\_comment, value); }
}
private DateTime \_dateAdded;
public DateTime DateAdded
{
get { return this.\_dateAdded; }
set { this.SetProperty(ref this.\_dateAdded, value); }
}
private int \_timeEstimate;
public int TimeEstimate
{
get { return this.\_timeEstimate; }
set { this.SetProperty(ref this.\_timeEstimate, value); }
}
private int \_timeSpent;
public int TimeSpent
{
get { return this.\_timeSpent; }
set { this.SetProperty(ref this.\_timeSpent, value); }
}
private int \_importanceScore;
public int ImportanceScore
{
get { return this.\_importanceScore; }
set { this.SetProperty(ref this.\_importanceScore, value); }
}
private int \_urgencyScore;
public int UrgencyScore
{
get { return this.\_urgencyScore; }
set { this.SetProperty(ref this.\_urgencyScore, value); }
}
private int \_worthScore;
public int WorthScore
{
get { return this.\_worthScore; }
set { this.SetProperty(ref this.\_worthScore, value); }
}
private bool \_accomplished;
public bool Accomplished
{
get { return this.\_accomplished; }
set { this.SetProperty(ref this.\_accomplished, value); }
}
}
}
[/sourcecode]
Create two repository classes, one for Activities and on for Categories. We will keep the repositories simple, no generic repository and no interfaces. Add the following method: Add, Remove, Update and GetAll. Let the constructor require a list of activities in the Activity repo and set the private field to the parameter. We will add the category repo next time, but it is basically almost identical.
[sourcecode language=“csharp”]
using Mihsp.Model;
using System.Collections.ObjectModel;
namespace Mihsp.Service
{
public class StudyActivityRepository
{
private ObservableCollection _studyActivities;
public StudyActivityRepository(ObservableCollection<StudyActivity> studyActivities)
{
this.\_studyActivities = studyActivities;
}
public void Add(StudyActivity studyActivity)
{
//TODO
}
public void Remove(StudyActivity studyActivity)
{
//TODO
}
public void Update(StudyActivity newActivity, StudyActivity oldActivity)
{
//TODO
}
public ObservableCollection<StudyActivity> GetAll()
{
return \_studyActivities;
}
}
}
[/sourcecode]
For now I will just implement the GetAll method for activities to show you how we can bind up the data to the view. The GetAll simply returns the items in the private field as an ObservableCollection.
In the view add a name to the listView like so : x:Name=“itemListView”
.
In the code behind we will wire it up like so (ignore the TestData for the graph control, we will re-wire that to the activities later on):
[sourcecode language=“csharp”]
using Mihsp.Model;
using Mihsp.Service;
using System.Collections.ObjectModel;
using Windows.UI.Xaml.Controls;
namespace Mihsp
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
SetListviewSource();
\_allEntries = new ObservableCollection<TestData>()
{
new TestData {Category = "Cats", NrOfEntries = 4},
new TestData {Category = "Dogs", NrOfEntries = 4},
new TestData {Category = "Birds", NrOfEntries = 6},
new TestData {Category = "Snakes", NrOfEntries = 2},
};
}
void SetListviewSource()
{
itemListView.ItemsSource = new StudyActivityRepository(CreateActivities()).GetAll();
}
ObservableCollection<StudyActivity> CreateActivities()
{
return new ObservableCollection<StudyActivity>()
{
new StudyActivity { Title = "Catify Framework", CategoryName = "Cat", Comment = "Look up the article in Wiki, nice info there " },
new StudyActivity { Title = "Dog language", CategoryName = "Dog", Comment = "Bla bla bla can't come up with something " }
};
}
private ObservableCollection<TestData> \_allEntries = new ObservableCollection<TestData>();
public ObservableCollection<TestData> AllEntries
{
get { return \_allEntries; }
}
public class TestData
{
public string Category { get; set; }
public int NrOfEntries { get; set; }
}
}
}
[/sourcecode]
Set a breakpoint and notice that we receive the data.
.
Next time we will set up a basic DataTemplate for the data we received and we will continue to work on the repositories!
Comments
I think that it is needed to make the object.Equals in the SetProperty method on the BindableBase class work.
The reason why the ref keyword is used in SetProperty(ref T storage, T value, ....) method in BindableBase is because the method contains this line of code: storage = value; That way, the value set in this method is also set in the variable sent in by the caller. Try removing the ref keyword and you'll see that _title won't get a value in StudyActivity after SetProperty(this._title, value) is called. A demo application showing the behavior is provided in the MSDN documentation here: http://msdn.microsoft.com/en-us/library/14akc2c7(v=vs.71).aspx
Hey Thanks for the explanation. I'll going to look you're provide link on MSDN to get the informationes needed.
Last modified on 2012-09-03