Home > .NET, Mobile > MonoMobile.MVVM, Round 2

MonoMobile.MVVM, Round 2

June 18th, 2011

So, from part 1 with MonoMobile.MVVM we can add some controls to a screen. That has limited usefulness since rarely do you need just one page a few entry controls for any apps, even data driven apps.

Now let’s make something that’s almost useful. We won’t persist data right now, but that can be tacked on later.

We’ll have to start with a new View.

public class NotesView : View
{
	public NotesView ()
	{
		var dataModel = new NotesDataModel ();
		Notes = new ObservableCollection<NoteViewModel> ();
		foreach (var item in dataModel.Load ())
			Notes.Add (item);
	}
	[List(ViewType = typeof(NoteView))]
	public ObservableCollection<NoteViewModel> Notes { get; set; }
}

We apply the [List] attribute so that this property is the basis for this view.The constructor loads up a DataModel to generate some generic data. I wouldn’t worry about that part right now, it will change when we build in persistance later.

Just for completeness, here’s my DataModel


public class NotesDataModel
{
	public IEnumerable<NoteViewModel> Load ()
	{
		return new List<NoteViewModel> {
				new NoteViewModel { Name = "One" },
				new NoteViewModel { Name = "Two" },
				new NoteViewModel { Name = "Three" },
				new NoteViewModel { Name = "Four" },
				new NoteViewModel { Name = "Five" },
				new NoteViewModel { Name = "Six" },
				new NoteViewModel { Name = "Seven" },
				new NoteViewModel { Name = "Eight" },
				new NoteViewModel { Name = "Nine" },
				new NoteViewModel { Name = "Ten" },
				new NoteViewModel { Name = "Eleven" },
				new NoteViewModel { Name = "Dozen" }
			};
	}
}

So we need the NoteViewModel since that’s what we’re binding to the front end…

public class NoteViewModel : ViewModel
{
	public string Name {
		get { return Get (() => Name); }
		set { Set (() => Name, value); }
	}
	public string Text {
		get { return Get (() => Text); }
		set { Set (() => Text, value); }
	}

	public override string ToString ()
	{
		return Name;
	}
}

Note: See Robert’s comment below, but the Get(() => ...) and Set(() => ...) blocks are helpers for INotifyPropertyChanged implementations.

The ToString() override is important. This is what is used to define what appears in the list view for each item. Play around with the ToString() if you want to have some fun! The Get and Set overrides supports notifications between data bindings.

Last thing we need to add is the view referenced to display the actual note details

public class NoteView : View
{
	[Section]
	[Entry]
	public string Name { get; set; }

	[Section("Note")]
	[Entry]
	[Multiline]
	[Caption("")]
	public string Text { get; set; }
}

Then from our last example, you’ll need to change the starting view.

public class Application : MonoMobileApplication
{
	public static new void Main (string[] args)
	{
		Run ("Sample", typeof(NotesView), args);
	}
}

This should get you to a working example. Nothing amazing. Next time we can consider persistance!

Categories: .NET, Mobile Tags: , , ,
  1. Robert Kozak
    June 20th, 2011 at 15:15 | #1

    Just wanted to point out that [Root] and [List] are interchangeable. [List] is used for taking the contents (Elements) of the collection and laying them out in one Section on the current page. A [Root] takes the items of a collection and places them under a Root Element when tapped navigates to a separate page with the Elements.

    So in your NotesView you can change lines 10 and 11 to this: [List(ViewType = typeof(NoteView))]

  2. Robert Kozak
    June 20th, 2011 at 15:22 | #2

    Also I want to point out what is so special about the Get() and Set() in the NoteViewModel. These methods are defined in the ObservableObject class that ViewModel derives from and they call INotifyPropertyChanged.PropertyChanged so that when a property changes the Databinding can update the UI automatically.

    The reason they take a lambda (()=>Text) is for compile time type checking. Normally INotifyPropertyChanged implementations takes a string name as a parameter and I find this too prone to error. So by using Set(()=>Text) it will turn the Property into a string and call it for you plus if you make a mistake and type Set(()=>Test) it will fail at compile time.

    You can ignore this and handle property changed yourself but I suggest sticking with this pattern because it is so much easier, better looking, and safer.

  3. June 22nd, 2011 at 20:02 | #3

    I’ve updated the post to reflect your comments. Thanks.

Comments are closed.