Navigation in MVVM
One of the main issues regarding Silverlight was the navigation issue,
what commonly refers as “How can we support browser’s back button”.
Although Microsoft has standard solution for that is somewhat limited. It’s
limitation concerns two main issues:
1. Navigation requires as to use Page Navigation and not user controls
2. It won’t support scenario when pressing a link changes the internal state
but will replace the entire page instead.
In this post, I’ll demonstrate how we can overcome these issues.
The post content is based on material leaned from Elad Katz of which
I’m trying to implement everywhere I can.
What do we need exactly to overcome the two limitation written above:
We need to have a class that acts as Navigation Service. The service should contain
an underlying Navigation Frame and handle all it’s events. One close look on the
automatically made Silverlight Navigation application reveals that the MainPage
does it exactly.
Because this service will serve our entire application it is SingleTon, we initally
send our navigation frame as parameter to the InitializeFrame method which look
like that:
public void InitializeFrame(Frame frame)
{
_frame = frame;
_frame.Navigated += (sender, e) =>
{
if (Navigated != null)
Navigated(this, e);
};
_frame.Navigating += (sender, e) =>
{
if (Navigating != null)
Navigating(this, e);
};
_frame.NavigationFailed += (sender, e) =>
{
if (NavigationFailed != null)
NavigationFailed(this, e);
};
_frame.NavigationStopped += (sender, e) =>
{
if (NavigationStopped != null)
NavigationStopped(this, e);
};
}
The service holds the same events as the navigation frame and invokes them, ,moreover it sets a private member with typed Frame called _frame which. This private member is the
same frame defined in the main page, where it’s entire code-behind looks exactly like that:
public partial class NavigationFrame : UserControl
{
public NavigationFrame()
{
InitializeComponent();
NavigationService.Instance.InitializeFrame(MyFrame);
}
}
The navigation frame is the main page of our application – the same
as the navigation application template in visual studio.
Now, every ViewModel can interact with the NavigationService, it can subscribe
to it’s events and from this point further, the sky is the limit…
In Conclusion:
In this post I discussed the limitation of Silverlight Navigation and introduced the
Navigation service. Doing it right can make our application support the “Back / Forward”
buttons of our browser.
I’ve chosen to demonstrate it through a simple RSS reader. You can download code example
here. The application’s UI may not look so good, but hey – It’s MVVM. you can change it easily…
MVVM – Using commands
On my previous post I’ve talked about MVVM in general. I’ve also
demonstrated how data binding with ViewModel works.
There is, however, issue with buttons: Buttons won’t cause
property changes (like TextBox, ComboBox etc. where
you can have TwoWay binding mode) and therefor we cannot
cause the ViewModel to run code through property setters.
So, what do we do?
On non-MVVM scenario we will simply create an EventHandler
on our code-behind and attach it to our Click event . However,
now we want to keep our code-behind as clean as possible.
In this post, I’ll demonstrate how to do so, using the button’s
Commnand property.
The button’s Command property type is ICommand , you can
implement this interface yourselves, however there
is an implementation of class called RelayCommand
on MVVM light toolkit you can use. binding your button’s
command property will cause the ViewModel to run method
when your button is clicked.
How to bind button to command:
1. On your ViewModel create a property with type that
implements ICommand .
public ICommand ButtonPressed { get; set; }
2. Now, on your View-Model constructor, initialize your command property
so it’s Execute method will run a method on your View-Model class. On
RelayCommand it should look like that:
ButtonPressed = new RelayCommand(ButtonPressedMethod);
Where ButtonPressedMethod is the method to be run when button clicked.
(Kind of replacing your EventHandler for click event when used code-behind)
3. Now, Bind on your View .xaml file, your button to the command:
<Button Command="{Binding Path=ButtonPressed}"…
Well, That’s it…
Summary
In order to simply execute code when button is clicked we use Command property.
Command is silverlight button’s property, typed ICommand that has an Execute
method. This method should cause the execution of our code. If we implement the
interface we have to take care that the Execute command will run our code, Using
MVVM’s RelayCommand we can simply send our method as a parameter to the
command’s constructor.
You can download demo Here
MVVM for Silverlight – what is it about?
I recently had the pleasure of having Elad Katz as a consultant for the customer 
I work for on Sela’s behalf. Elad’s job was to lead us migrating a “regular”
Silverlight project to MVVM .
This post is the first in a series discussing MVVM and it’s application in
Silverlight. In here I’ll discuss about what MVVM is all about and what are
it’s advantages.
What is MVVM ?
MVVM is a design pattern aimed mainly to separate (and decouple)
the graphic design from it’s data and behavior (It is based on MVC
and MVP but differs, leveraging the XAML advantages).
MVVM stands for Model View ViewModel:
Model – The data context or the data access representing the context (The same as MVC)
View – The graphic design. Views are XAML files mainly user controls.
View-Model – The “Model of the View” : Acts as the view’s data context. The View-Model
has also the logical behavior, mostly everything you’ll find on a user control’s code behind
should be in a View-Model
Relations:
View “knows” the View-Model as it’s data context. The view’s child control has data
bindings to various properties of the View-Model
View-Model calls services and performs client logics. This means that in most cases,
you shouldn’t write anything on the Views code-behind.
This separation gives as, along with code readability (once you get used to the pattern)
is the ability to test UI behavior, and with proper mocking, you can see how the controls
and pages can look like with some actual data.
Moreover, because of this separation, you may change your view’s appearance , layout etc.
without touching it’s behavior. Try without MVVM to replace type of controls, remove control
and so on. ’m sure that every change of this kind causes changes in various places on your
code-behind.
You can read detailed information about it Here and Here, however, in order to best
understand the concept, let’s see how View and View-Model work together.
How does it work
I’m sure you’re all familiar with this line of XAML:
<TextBlock Text="{Binding Path=TimePicked, Mode=OneWay}"></TextBlock>
For those of you who aren’t : This binds a property to a control (Textblock
in this case ) but have we thought to have a DataContext as a class that’s has
all what we have in our code-behind?
Well, that’s actually the main idea behind MVVM .The view’s control’s properties
are bound to the View-Model properties.
So, Let’s build a simple View-Model demo:
1. Because View-Model properties are bound to the view’s inner controls, it should
implement the INotifyPropertyChanged interface.
2. Every set to the property has to invoke the PropertyChanged event on every
set, meaning that a property should look like that.
private DateTime timePicked = DateTime.MinValue;
public DateTime TimePicked
{
get
{
return timePicked;
}
set
{
timePicked = value;
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs("TimePicked"));
}
}
}
That’s how we make sure that property recent value is always shown on it’s bound
control.
3. Now, let’s change the TimePicked property. In here we do it every second
This piece of code should do so.
DispatcherTimer timer;
public TimeViewModel()
{
timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 1);
timer.Tick += Timer_Elapsed;//
timer.Start();
}
private void Timer_Elapsed(object sender, EventArgs e)
{
TimePicked = DateTime.Now;
}
In here, we’ve set a timer on our View-Model constructor. you can see that it is a private member
of the View-Model, no other class (including views) should know it.
4. Let’s attach the View-Model to the view. All we need to do is set our DataContext property.
You may use ViewModelLocator In here I’ve put the ViewModel in my application resources
and set the DataContext property in my user control (view) like that:
(App.Xaml)
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MVVMDemo.App"
xmlns:vm="clr-namespace:MVVMDemo.ViewModels"
>
<Application.Resources>
<vm:TimeViewModel x:Key="TimeViewModel"></vm:TimeViewModel>
</Application.Resources>
</Application>
(User control attribute on root node)
DataContext="{StaticResource TimeViewModel}"
Now, all we have to do is compile the application, then we can see the TextBlock
switches values as time goes by.You might notice that it does so even on design
time, think how great it is for the graphic designer who can see how the application
would look like, with actual data in it.
Summary
I’ve talked a little bit about what MVVM is, demonstrated it by a (very small) demo
and showed how a DataContext can control logic behavior of view, and do so|
without knowing the view itself. Main advantages are the ability to change the
view without touching the ViewModel and of course test the ViewModel
and overcome the difficulties of UI-testing.
You can download the full source from here