4. ViewModel
• Properties
• Commands
• INotifyPropertyChanged
Model
• Entities (POCO)
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
5. ViewModel
• Properties
• Commands
• INotifyPropertyChanged
Model
• Entities (POCO)
Application
• ViewModels instance
• Navigation context
• Navigation transitions
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
Navigator
• Navigate to view
implementation
Entry
Point
6. ViewModel
• Properties
• Commands
• INotifyPropertyChanged
Application
• ViewModels instance
• Navigation context
• Navigation transitions
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
Navigator
• Navigate to view
implementation
Entry
Point
7.
8.
9.
10.
11.
12.
13.
14. Main View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
Main ViewModel
• Properties
• Commands
• INotifyPropertyChanged
SubB ViewModel
• Properties
• Commands
• INotifyPropertyChanged
SubA ViewModel
• Properties
• Commands
• INotifyPropertyChanged
SubB View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
SubA View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
Composite ViewModels are also possible:
class MainViewModel : ViewModelBase {
List<ItemViewModel> MyItems /* Data-Bindable property
}
15.
16.
17. ViewModel
• Properties
• Commands
• INotifyPropertyChanged
public int Count /* One-way data-bindable property
generated with propdb1 snippet …
public string MyProperty /* Two-way data-bindable
property generated with propdb2 snippet …
public string MyProperty2 /* Two-way data-bindable
property that calls custom code in
OnMyProperty2Changed() from setter, generated with
propdb2c snippet …
/* One-way data-bindable property generated with
propdbcol snippet…
public ObservableCollection<string> MyCollection
public bool MyCollectionHasItems
protected void UpdateMyCollectionHasItems()
18. ViewModel
• Properties
• Commands
• INotifyPropertyChanged
public RelayCommand DoSomethingCommand /* Data-bindable
command that calls DoSomething(), generated with cmd
snippet …
private void DoSomething()
{
// TODO: Implement DoSomething()
throw new NotImplementedException();
}
public RelayCommand EditItemCommand /* Data-bindable
command with parameter that calls EditItem(), generated
with cmdp snippet …
private void EditItem(object parameter)
{
var item = (Item)parameter;
// TODO: Implement EditItem()
throw new NotImplementedException();
}
19. ViewModel
• Properties
• Commands
• INotifyPropertyChanged
// Design-time data support
#if DEBUG
namespace MyApp.ViewModels.Design
{
public class MyModelDesign : MyViewModel
{
public MyModelDesign()
{
// TODO: Initialize the view model with
hardcoded design-time data
}
}
}
#endif
Note: Design-data can initially also be used at runtime
for fast application prototyping, before any services or
models are implemented.
20. ViewModel
• Properties
• Commands
• INotifyPropertyChanged
public abstract class ViewModelBase :
INotifyPropertyChanged
{
public event PropertyChangedEventHandler
PropertyChanged;
protected virtual void RaisePropertyChanged(
string propertyName)
{ … }
}
public class RelayCommand : ICommand
{
public RelayCommand(Action handler, …
public RelayCommand(Action<object> handler, …
public bool IsEnabled { … }
}
21. ViewModel
• Properties
• Commands
• INotifyPropertyChanged
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
<phone:PhoneApplicationPage
xmlns:vm=
"clr-namespace:MyApp.Shared.ViewModels.Design;
assembly=MyApp.Shared.wp"
d:DataContext="{d:DesignInstance
Type=vm:MyViewModelDesign,
IsDesignTimeCreatable=True }"
<TextBox Text="{Binding Title, Mode=TwoWay}" …
</phone:PhoneApplicationPage>
public partial class MyView : PhoneApplicationPage
{
public MyView()
{
InitializeComponent();
DataContext = MyApplication.Instance.MyViewModel;
}
}
22. ViewModel
• Properties
• Commands
• INotifyPropertyChanged
Model
• Entities (POCO)
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
public class ClientLotUpdate
{
public decimal CurrentPrice { get; set; }
public int ProgressRemaining { get; set; }
public RemainingTime TimeRemaining { get; set; }
public ClientLotUpdate()
{
TimeRemaining = new RemainingTime();
}
}
23. ViewModel
• Properties
• Commands
• INotifyPropertyChanged
ServiceAgent
• Service Entities
• Service Events
• Service Methods
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
public class ClientLotUpdate
{
public decimal CurrentPrice { get; set; }
public int ProgressRemaining { get; set; }
public RemainingTime TimeRemaining { get; set; }
public ClientLotUpdate()
{
TimeRemaining = new RemainingTime();
}
}
Note that in simple cases service entities defined in
the service contract can be used directly as the
‘model’.
24. ViewModel
• Properties
• Commands
• INotifyPropertyChanged
Model
• Entities (POCO)
ServiceAgent
• Service Entities
• Service Events
• Service Methods
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
public class LotUpdatedEventArgs : EventArgs
{
public ClientLotUpdate clientLotUpdate { get; set; }
}
public event EventHandler<LotUpdatedEventArgs>
ActiveLotUpdated;
25. ViewModel
• Properties
• Commands
• INotifyPropertyChanged
Model
• Entities (POCO)
ServiceAgent
• Service Entities
• Service Events
• Service Methods
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
public class PlaceBidRequest
{
public int LotId { get; set; }
public decimal Price { get; set; }
}
public Task RaisePlaceBidAsync(PlaceBidRequest
placeBidRequest)
{
return _hubProxy.Invoke(
"PlaceBid",
new object[] { placeBidRequest });
}
26. ViewModel
• Properties
• Commands
• INotifyPropertyChanged
Model
• Entities (POCO)
ServiceAgent
• Service Entities
• Service Events
• Service Methods
Application
• ViewModels instance
• Navigation context
• Navigation transitions
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
public class AuctionApplication
{
void ContinueToAuction()
void ContinueToCheckout(Basket basket)
void ContinueToOrderConfirmed()
void ContinueToProductList()
void ContinueToProductPage(ClientLot product)
void UserWantsToSignIn()
bool IsUserLoggedIn()
…
}
The ViewModel only uses the application to initiate
navigation and to obtain relevant application state.
ViewModels do not reference or modify other viewmodels.
Exception: contained view models; e.g. a collection of
ItemViewModel.
ViewModels can pass parameters to the application, which
in turn can use those to initialize other view models.
27. ViewModel
• Properties
• Commands
• INotifyPropertyChanged
Model
• Entities (POCO)
ServiceAgent
• Service Entities
• Service Events
• Service Methods
Application
• ViewModels instance
• Navigation context
• Navigation transitions
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
public abstract class ApplicationBase {
public static Task RunOnUIThread(Action action)
public object CurrentNavigationContext { get; set; }
}
class MyApplication : ApplicationBase {
public static MyApplication Instance { get … }
public MyViewModel MyViewModel { get; private set; }
public void ContinueToItem(Item item = null)
{
if (MyViewModel == null)
MyViewModel = new MyViewModel(_itemService);
MyViewModel.Initialize(item);
RunOnUIThread(() => _navigator.NavigateToMyView(
CurrentNavigationContext));
}
}
Application initializes viewmodel and then calls
navigator for platform-specific view navigation.
28. ViewModel
• Properties
• Commands
• INotifyPropertyChanged
Model
• Entities (POCO)
ServiceAgent
• Service Entities
• Service Events
• Service Methods
Application
• ViewModels instance
• Navigation context
• Navigation transitions
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
Navigator
• Navigate to view
implementation
public interface IMyAppNavigator
{
void NavigateToMyView(object navigationContext);
void NavigateToOtherView(object navigationContext);
}
The navigator implementation is platform specific – it
knows what type of object navigationContext is.
29. ViewModel
• Properties
• Commands
• INotifyPropertyChanged
Model
• Entities (POCO)
ServiceAgent
• Service Entities
• Service Events
• Service Methods
Application
• ViewModels instance
• Navigation context
• Navigation transitions
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
Navigator
• Navigate to view
implementation
Entry
Point
public partial class App : Application {
public static MyApplication EnsureMyApplication(
Frame navigationContext) {
return MyApplication.Instance ??
new MyApplication(new MyNavigator(),
navigationContext);
}
void Application_Launching(…) {
EnsureMyApplication(RootFrame).ContinueToItemList(
skipNavigation: true);
}
void Application_Activated(…) {
EnsureMyApplication(RootFrame);
}
}
The entry point is platform specific
(navigationContext, here a WP Frame) and creates
platform specific service instances, such as the
Navigator.
30. ViewModel
• Properties
• Commands
• INotifyPropertyChanged
Model
• Entities (POCO)
ServiceAgent
• Service Entities
• Service Events
• Service Methods
Application
• ViewModels instance
• Navigation context
• Navigation transitions
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
Navigator
• Navigate to view
implementation
Entry
Point
class MyNavigator : IMyNavigator
{
void Navigate(object navigationContext, string uri)
{
((Frame)navigationContext).Navigate(
new Uri(uri, UriKind.Relative));
}
void NavigateToMyView(object navigationContext)
{
Navigate(navigationContext, "/MyView.xaml");
}
…
}
The navigator is platform specific (navigationContext,
here a WP Frame).
31. ViewModel
• Properties
• Commands
• INotifyPropertyChanged, INoti
fyCollectionChanged
Model
• Entities (POCO)
ServiceAgent
• Service Entities
• Service Events
• Service Methods
Application
• ViewModels instance
• Navigation context
• Navigation transitions
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
Navigator
• Navigate to view
implementation
Entry
Point
Runtime flow: Application starts with AuctionView, user
places bid and navigates to CheckoutView.
1. Entrypoint is called, creates Navigator and
Application instances.
2. Application ctor creates ServiceAgent and
AuctionViewModel + ProductsViewModel
3. Entry Point calls
MyApplication.Instance.NavigateToAuctionView()
4. Navigator calls platform-specific navigate to
AuctionView
5. View class gets ViewModel from Application.Instance
6. On platforms without data binding, the view
subscribes itself to PropertyChanged on
ViewModel, for select (groups of) properties (it is
not necessary to bind to each individual property).
Also the commands of the views are invoked from code
in an event handler.
7. The viewmodel is updated by events from service and
commands from view. The view updates w data binding.
8. A command on a viewmodel can invoke the ContinueTo…
method on application … continue with step 3.
1
2
3
4
5 6
78
2
32. ViewModel
• Properties
• Commands
• INotifyPropertyChanged, INoti
fyCollectionChanged
Model
• Entities (POCO)
ServiceAgent
• Service Entities
• Service Events
• Service Methods
Application
• ViewModels instance
• Navigation context
• Navigation transitions
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
Navigator
• Navigate to view
implementation
Entry
Point
Runtime flow: Application starts with AuctionView, user
places bid and navigates to CheckoutView.
1. Entrypoint is called, creates Navigator and
Application instances.
2. Application ctor creates ServiceAgent and
AuctionViewModel + ProductsViewModel
3. Entry Point calls
MyApplication.Instance.NavigateToAuctionView()
4. Navigator calls platform-specific navigate to
AuctionView
5. View class gets ViewModel from Application.Instance
6. On platforms without data binding, the view
subscribes itself to PropertyChanged on
ViewModel, for select (groups of) properties (it is
not necessary to bind to each individual property).
Also the commands of the views are invoked from code
in an event handler.
7. The viewmodel is updated by events from service and
commands from view. The view updates w data binding.
8. A command on a viewmodel can invoke the ContinueTo…
method on application … continue with step 3.
1
2
3
4
5 6
78
2
33. ViewModel
• Properties
• Commands
• INotifyPropertyChanged, INoti
fyCollectionChanged
Model
• Entities (POCO)
ServiceAgent
• Service Entities
• Service Events
• Service Methods
Application
• ViewModels instance
• Navigation context
• Navigation transitions
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
Navigator
• Navigate to view
implementation
Entry
Point
Runtime flow: Application starts with AuctionView, user
places bid and navigates to CheckoutView.
1. Entrypoint is called, creates Navigator and
Application instances.
2. Application ctor creates ServiceAgent and
AuctionViewModel + ProductsViewModel
3. Entry Point calls
MyApplication.Instance.NavigateToAuctionView()
4. Navigator calls platform-specific navigate to
AuctionView
5. View class gets ViewModel from Application.Instance
6. On platforms without data binding, the view
subscribes itself to PropertyChanged on ViewModel,
for select (groups of) properties (it is not
necessary to bind to each individual property). Also
the commands of the views are invoked from code in an
event handler.
7. The viewmodel is updated by events from service and
commands from view. The view updates w data binding.
8. A command on a viewmodel can invoke the ContinueTo…
method on application … continue with step 3.
1
2
3
4
5 6
78
2
34. ViewModel
• Properties
• Commands
• INotifyPropertyChanged, INoti
fyCollectionChanged
Model
• Entities (POCO)
ServiceAgent
• Service Entities
• Service Events
• Service Methods
Application
• ViewModels instance
• Navigation context
• Navigation transitions
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
Navigator
• Navigate to view
implementation
Entry
Point
Runtime flow: Application starts with AuctionView, user
places bid and navigates to CheckoutView.
1. Entrypoint is called, creates Navigator and
Application instances.
2. Application ctor creates ServiceAgent and
AuctionViewModel + ProductsViewModel
3. Entry Point calls
MyApplication.Instance.NavigateToAuctionView()
4. Navigator calls platform-specific navigate to
AuctionView
5. View class gets ViewModel from Application.Instance
6. On platforms without data binding, the view
subscribes itself to PropertyChanged on
ViewModel, for select (groups of) properties (it is
not necessary to bind to each individual property).
Also the commands of the views are invoked from code
in an event handler.
7. The viewmodel is updated by events from service and
commands from view. The view updates w data binding.
8. A command on a viewmodel can invoke the ContinueTo…
method on application … continue with step 3.
1
2
3
4
5 6
78
2
35. ViewModel
• Properties
• Commands
• INotifyPropertyChanged, INoti
fyCollectionChanged
Model
• Entities (POCO)
ServiceAgent
• Service Entities
• Service Events
• Service Methods
Application
• ViewModels instance
• Navigation context
• Navigation transitions
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
Navigator
• Navigate to view
implementation
Entry
Point
Runtime flow: Application starts with AuctionView, user
places bid and navigates to CheckoutView.
1. Entrypoint is called, creates Navigator and
Application instances.
2. Application ctor creates ServiceAgent and
AuctionViewModel + ProductsViewModel
3. Entry Point calls
MyApplication.Instance.NavigateToAuctionView()
4. Navigator calls platform-specific navigate to
AuctionView
5. View class gets ViewModel from Application.Instance
6. On platforms without data binding, the view
subscribes itself to PropertyChanged on
ViewModel, for select (groups of) properties (it is
not necessary to bind to each individual property).
Also the commands of the views are invoked from code
in an event handler.
7. The viewmodel is updated by events from service and
commands from view. The view updates w data binding.
8. A command on a viewmodel can invoke the ContinueTo…
method on application … continue with step 3.
1
2
3
4
5 6
78
2
36. ViewModel
• Properties
• Commands
• INotifyPropertyChanged,
INotifyCollectionChanged
Model
• Entities (POCO)
ServiceAgent
• Service Entities
• Service Events
• Service Methods
Application
• ViewModels instance
• Navigation context
• Navigation transitions
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
Navigator
• Navigate to view
implementation
Entry
Point
Runtime flow: Application starts with AuctionView, user
places bid and navigates to CheckoutView.
1. Entrypoint is called, creates Navigator and
Application instances.
2. Application ctor creates ServiceAgent and
AuctionViewModel + ProductsViewModel
3. Entry Point calls
MyApplication.Instance.NavigateToAuctionView()
4. Navigator calls platform-specific navigate to
AuctionView
5. View class gets ViewModel from Application.Instance
6. On platforms without data binding, the view
subscribes itself to PropertyChanged on
ViewModel, for select (groups of) properties (it is
not necessary to bind to each individual property).
Also the commands of the views are invoked from code
in an event handler.
7. The viewmodel is updated by events from service and
commands from view. The view updates w data binding.
8. A command on a viewmodel can invoke the ContinueTo…
method on application … continue with step 3.
1
2
3
4
5 6
78
2
37. ViewModel
• Properties
• Commands
• INotifyPropertyChanged, INoti
fyCollectionChanged
Model
• Entities (POCO)
ServiceAgent
• Service Entities
• Service Events
• Service Methods
Application
• ViewModels instance
• Navigation context
• Navigation transitions
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
Navigator
• Navigate to view
implementation
Entry
Point
Runtime flow: Application starts with AuctionView, user
places bid and navigates to CheckoutView.
1. Entrypoint is called, creates Navigator and
Application instances.
2. Application ctor creates ServiceAgent and
AuctionViewModel + ProductsViewModel
3. Entry Point calls
MyApplication.Instance.NavigateToAuctionView()
4. Navigator calls platform-specific navigate to
AuctionView
5. View class gets ViewModel from Application.Instance
6. On platforms without data binding, the view
subscribes itself to PropertyChanged on
ViewModel, for select (groups of) properties (it is
not necessary to bind to each individual property).
Also the commands of the views are invoked from code
in an event handler.
7. The viewmodel is updated by events from service and
commands from view. The view updates w data binding.
8. A command on a viewmodel can invoke the ContinueTo…
method on application … continue with step 3.
1
2
3
4
5 6
78
2
38. ViewModel
• Properties
• Commands
• INotifyPropertyChanged, INoti
fyCollectionChanged
Model
• Entities (POCO)
ServiceAgent
• Service Entities
• Service Events
• Service Methods
Application
• ViewModels instance
• Navigation context
• Navigation transitions
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
Navigator
• Navigate to view
implementation
Entry
Point
Runtime flow: Application starts with AuctionView, user
places bid and navigates to CheckoutView.
1. Entrypoint is called, creates Navigator and
Application instances.
2. Application ctor creates ServiceAgent and
AuctionViewModel + ProductsViewModel
3. Entry Point calls
MyApplication.Instance.NavigateToAuctionView()
4. Navigator calls platform-specific navigate to
AuctionView
5. View class gets ViewModel from Application.Instance
6. On platforms without data binding, the view
subscribes itself to PropertyChanged on
ViewModel, for select (groups of) properties (it is
not necessary to bind to each individual property).
Also the commands of the views are invoked from code
in an event handler.
7. The viewmodel is updated by events from service and
commands from view. The view updates w data binding.
8. A command on a viewmodel can invoke the ContinueTo…
method on application … continue with step 3.
1
2
3
4
5 6
78
2
39. ViewModel
• Properties
• Commands
• INotifyPropertyChanged, INoti
fyCollectionChanged
Model
• Entities (POCO)
ServiceAgent
• Service Entities
• Service Events
• Service Methods
Application
• ViewModels instance
• Navigation context
• Navigation transitions
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
Navigator
• Navigate to view
implementation
Entry
Point
Runtime flow: Application starts with AuctionView, user
places bid and navigates to CheckoutView.
1. Entrypoint is called, creates Navigator and
Application instances.
2. Application ctor creates ServiceAgent and
AuctionViewModel + ProductsViewModel
3. Entry Point calls
MyApplication.Instance.NavigateToAuctionView()
4. Navigator calls platform-specific navigate to
AuctionView
5. View class gets ViewModel from Application.Instance
6. On platforms without data binding, the view
subscribes itself to PropertyChanged on ViewModel,
for select (groups of) properties (it is not
necessary to bind to each individual property). Also
the commands of the views are invoked from code in an
event handler.
7. The viewmodel is updated by events from service and
commands from view. The view updates w data binding.
8. A command on a viewmodel can invoke the ContinueTo…
method on application … continue with step 3.
1
2
3
4
5 6
78
2
40. ViewModel
• Properties
• Commands
• INotifyPropertyChanged, INoti
fyCollectionChanged
Model
• Entities (POCO)
ServiceAgent
• Service Entities
• Service Events
• Service Methods
Application
• ViewModels instance
• Navigation context
• Navigation transitions
View
• Markup
• Data binding code
(if not supported in markup)
• UI Manipulation Code
Navigator
• Navigate to view
implementation
Entry
Point
Runtime flow: Application starts with AuctionView, user
places bid and navigates to CheckoutView.
1. Entrypoint is called, creates Navigator and
Application instances.
2. Application ctor creates ServiceAgent and
AuctionViewModel + ProductsViewModel
3. Entry Point calls
MyApplication.Instance.NavigateToAuctionView()
4. Navigator calls platform-specific navigate to
AuctionView
5. View class gets ViewModel from Application.Instance
6. On platforms without data binding, the view
subscribes itself to PropertyChanged on
ViewModel, for select (groups of) properties (it is
not necessary to bind to each individual property).
Also the commands of the views are invoked from code
in an event handler.
7. The viewmodel is updated by events from service and
commands from view. The view updates w data binding.
8. A command on a viewmodel can invoke the ContinueTo…
method on application … continue with step 3.
1
2
3
4
5 6
78
2