Advanced WPF

Download Report

Transcript Advanced WPF

© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
www.sela.co.il
Separated Presentation Patterns
MVVM
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
2
•
•
•
•
Motivation
Supervising Presenter
Presentation Model
Model View ViewModel
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
3
• Client application retrieves domain data, displays it and
allows the user to change it.
• Defining all the application logic in controls makes them
complex and difficult to understand, maintain, evolve, test
and re-use.
• Separated presentation patterns cleanly separate out the
visual portions of your application from the business and
presentation logic portions.
• Having a clean separation allows:
– Developers to focus on application logic
– Designers to focus on visual aspects
– Unit test independently
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
4
• Also known as Supervising Controller
• The View bound directly to the Model
• The Presenter coordinates any
additional interaction between the
View and the Model that cannot be
achieved through simple data binding.
• The Presenter encapsulates
presentation logic that interprets user
gestures into actions against the
Model; it also translates changes in the
Model into user interface actions.
IView
View
Presenter
Model
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
5
• The Presentation Model provides a façade over the Model and
coordinates all of the View's interaction with it.
• The Presentation Model is designed to be easily consumed by a
View
– The View can call methods, use data binding, commands, and other
behaviors to interact with it.
• The Presentation Model also frequently adapts the underlying
Model’s data into a form that is easier to represent in the user
interface.
• The popular MVVM pattern is a variant of this pattern.
View
Presentation
Model
Model
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
6
• Known as MVVM.
• MVVM is an implementation of Presentation Model
designed specifically for use with WPF and Silverlight.
• Very popular in the WPF and Silverlight community.
• The View-ViewModel interaction is done through Data
Binding only.
View
Data Binding
ViewModel
Model
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
7
•
•
•
•
•
•
•
Benefits of MVVM
The Model
The View
The ViewModel
View-ViewModel Gluing
Triggering ViewModel Actions
Attached Behaviors
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
8
• Share a project with a designer, and have the flexibility
for design work and development work to happen
near-simultaneously.
• Solution thorough unit testing.
• Reusable components, both within and across projects
in the organization.
• Flexibility to change the user interface without having
to refactor other logic in the code base.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
9
•
•
•
•
•
The Model represents an application domain object.
In a rich client application, the Model is part of the business layer, and represent a
business entity. The Model is responsible for holding and manipulating the business
data.
In a thin client application, the Model usually represents only a server side data
contract and not the business that manipulates it.
– Usually there is a service layer which transports data-contracts to and from the
server.
The Model shouldn’t contain any logic to directly interact with the user:
– Not responsible for formatting text to look prettier on the screen.
– Not responsible for holding any visual element.
– Must not reference any WPF element.
The model may contain data validation.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
10
• To maximize re-use opportunities, models should not
contain any use case–specific or user task–specific
behavior or application logic.
• The model may also include the code to support data
access and caching, though typically a separate data
repository or service is employed for this.
• Often, the model and data access layer are generated
as part of a data access or service strategy, such as the
ADO.NET Entity Framework, WCF Data Services, or
WCF RIA Services.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
11
• Doesn’t reference any type defined in
PresentationFramework.dll, System.Windows.Forms,
PresentationCore, etc.
• Theoretically, can be displayed in a Console Application.
• Doesn’t translate any content for the UI (Localized or Formatted
resource).
• In a thin client application, doesn’t contain business logic (this
should be implemented by the server).
– May contain client-specific business logic which is not related to the UI
• In a rich client application, no need of additional logic
concerning working with the model.
– Encapsulates business logic and data queries from the UI
• Raises only events when requiring feedback from the user.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
12
Customer is a domain object – a model
It is not related to any UI technology
In that specific case, It provides validation logic
In other cases it may implement the
INotifyPropertyChanged interface (more on this later)
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
13
•
•
•
•
Data Visualization implementation.
The view is the only piece the end user interacts with.
A view may have behaviors associated with it.
The view manages input (key presses, mouse
movements, touch gestures, etc) which mapped to
properties, method calls and commands of the viewmodel.
• The view is not responsible for maintaining its state.
Instead, it will synchronize this with the view-model.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
14
• Actually the view comes in two flavors: UserControl and
DataTemplate.
• Use user-control when the view:
– Is well-know at design time and can be statically created
– Requires code-behind (event handling, animation control, visual tree
manipulation, hit testing, access the view-model, etc.)
– Should be easily designed from VS and Blend
• Use data-template when the view:
– Is unknown at design time and must be dynamically created (you mustn't
create a View from a ViewModel, it breaks the MVVM concept)
– Should provide better decoupling from the view-model (data-template by
definition has no code-behind)
– Implicit data-template is supported (Silverlight 4 doesn’t support implicit
data-templates only Silverlight 5 will)
• You may combine both by creating a data-template and a user-control
as the single child of the data-template visual tree.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
15
• Drop event like
MouseMove and other
input related events are
view behaviors, hence
handled by the view and
mapped to view-model
properties, method calls
and commands.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
16
• Since we can’t register events in data-template the
view must be simple.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
17
• This approach comes in handy later, when trying to
connect the view with the view-model.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
18
• Free of logic that affects more than the UI itself.
• There’s exactly one UserControl per each ViewModel
class.
• References the view model through its DataContext
property.
• Uses only the ViewModel and not the Model.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
19
• The view-model is a key piece of the pattern because it introduces
Presentation Separation.
• The view-model holds the presentation logic behind the view, which
may include: presentation algorithms, error handling, fetching data
and interaction with other view-models.
• The view model coordinates the view's interaction with the model.
• The view-model does all the preparation so the view can easily bound
with it using data binding.
• The view-model may also expose methods and commands for
complex scenarios where there is no simple data-binding solution – in
that case the view may be coupled with the view-model but not vice
versa.
• The view model may define logical states that the view can represent
visually to the user.
• A view-model may be composite in terms of other view-models.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
20
• The view-model becomes wholly responsible for the
model in this scenario:
– Interacts with the model to fetch and manipulate business
data
– It may expose the model directly, or properties related to the
model, for data-binding
– It may reference data services in order to fetch and
manipulate the data it exposes to the view
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
21
• The view and the view-model communicate via databinding (usually), method calls, properties and events.
• The view-model exposes not only models, but other
properties, such as state information and commands.
• The view handles its own UI events, then maps them to
the view-model via commands.
• The models and properties on the view-model are
updated from the view via two-way data binding.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
22
• In general, a view should have exactly one view-model.
• A view may be composed of other views, each with its
own view-model.
• View models might compose other view-models when
necessary.
• A single view-model might be used by multiple views.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
23
• The view-model notifies
on property changes.
• Exposes models and
state via properties to
the view.
• Call services to fetch
data.
• Implements business
logic.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
24
• “Simple” to use and “easy” to test.
• Tracks property changes and report them via
INotifyPropertyChanged.
• All properties either return another ViewModel, a primitive
data type or a collection of one of these.
• Doesn’t combine two or more properties to a new one (use
value converter instead).
• There are commands for every action the view can trigger
on the ViewModel.
• Totally independent of the current UI.
• Doesn’t reference any visual element.
• Every action is exposed as a command.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
25
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
26
• Actually, there are three ways connecting the view and viewmodel together.
• View First
– The view creates or discovers the view model.
– The view typically binds to the view model as a resource, uses a viewmodel locator pattern, or has the view model injected via MEF, Unity, or
other.
• ViewModel First
– The view-model is responsible for creating the view and binding itself to
the view.
– View as data template flavor comes in handy using this approach.
• Marriage
– Third class (such as Controller) creates or discovers both the view and the
view-model, then connects them toghether.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
27
• Discovering or creating the view-model from the view
can be done directly or indirectly.
• Creating the view-model directly is not recommended:
– Couples the view with a specific view-model
– The view model may have dependencies that the view can’t
resolve
• The view-model can be retrieved indirectly using a
View-model Locator, DI Container such as Unity or MEF,
other.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
28
A View Model Locator is responsible to create or to locate
the view-model.
The view can use the view-model locator to retrieve the
view.
The View Model Locator can be created as XAML resource
and the view can resolve the view-model declaratively.
<Application ...>
<Application.Resources>
<local:ViewModelLocator x:Key="ViewModelLocator" />
</Application.Resources>
</Application>
<UserControl ...
DataContext="{Binding MyViewModel, Source={StaticResource ViewModelLocator}}">
...
</UserControl>
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
29
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
30
•
•
•
A DI container provides an easy way to resolve an object such as view-model with all
of its dependencies.
Using a DI container, a view-model can be easily retrieved by the corresponding view.
There are several free DI containers in the market:
– Castle Windsor based on the Castle MicroKernel:
• Licensed under Apache 2
• Well documented and very popular
– Spring.NET
• Licensed under Apache 2
• Written by Mark Pollack
– Unity
• Licensed as MS-PL
• Written by Chris Tavares.
• Build on the "kernel" of ObjectBuilder:
– Ninject formerly "Titan"
• Licensed under Apache 2
• Was quiet, but has recently sprung back to life.
• Written by Nate Kohari
•
The view-model locator can be based on a DI container.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
31
The Managed Extensibility Framework (MEF) is a new library
shipping in the .NET Framework 4 and in Silverlight 4 that
simplifies the design of composable systems that can be
extended by third parties after they have been deployed.
MEF opens up your applications, allowing new functionality to
be incrementally introduced by application developers,
framework authors and third-party extenders.
[Export(typeof(ISurfaceViewModel)), PartCreationPolicy(CreationPolicy.NonShared)]
public class SurfaceViewModel : NotificationObject, ISurfaceViewModel
{
[Import]
private ISurface Surface { get; set; }
public int SurfaceWidth
{
get { return Surface.Dimensions.Width; }
}
public int SurfaceHeight
{
get { return Surface.Dimensions.Height; }
}
}
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
32
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
33
• Since we are not dealing with UI elements in the view-model
anymore, there should be a simple way for the View to trigger
actions on the view-model.
• Actually there are several options:
– Delegate events from the view to the view-model by invoking view-model
methods directly from the view code behind.
– Expose commands as properties from the view-model so the view can
bind them to UI elements from XAML or code behind.
• The second option using commands has several benefits:
– Much less boilerplate code to write in the view code behind.
– Easy way to bind actions from design tools such as Blend.
– Command has availability state hence there is no need for special care in
such case.
– Great solution for views implemented as DataTemplate.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
34
• WPF introduces Routed Command as default
implementation for the ICommand interface.
• WPF routed commands deliver command messages
through UI elements in the visual tree.
• Separating the UI from the logic, the view-model
handles commands outside the visual tree.
• The WPF routed command implementation is not
suitable in that case since we currently don’t have
access to the visual tree.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
35
• Handling commands off the visual tree, we should have
custom implementation of the WPF ICommand interface.
• Relaying command is a custom implementation of
ICommand which simply relays the command execution to
the view-model instance using a simple delegate.
• Relaying command doesn’t depend on any visual tree.
• The view-model instantiate relaying commands, and expose
them to the view as properties.
• Since the view-model handles the execution of the
command, we don’t necessarily have to pass arguments.
The view-model already knows the view state.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
36
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
37
• Sometimes there is no option or there is no declarative
way to bind the view to the view-model:
– Several properties that don’t support data-binding, such as
TreeView.SelectedItem.
– Methods should be activated on the view such as
ListBox.ScrollIntoView.
– Trigger actions when routed events are raised by the view,
such as mouse, keyboard and touch events.
• WPF Attached Properties mechanism can be used to
close this gap.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
38
• Attached property is a property that is defined by a
different type than the element to which the property is
applied
• Attached property is commonly used by most of WPF’s
layout elements
• Attached properties are sophisticated way for extending a
well known, well used element with functionality and/or
state, without using inheritance.
• You can think of attached properties as extensionproperties used from XAML or code behind.
• Using attached properties you can implement several
patterns such as Attached Behavior.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
39
• The code snippet below shows how to create, register and then use an
attached property
public static class TreeViewProperties {
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.RegisterAttached(“SelectedItem",
typeof(object), typeof(TreeViewProperties),
new PropertyMetadata(null, SelectedItemChanged));
private static void SelectedItemChanged(
DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Implement Attached Property Logic
}
public object void SetSelectedItem(UIElement element, object value) {
element.SetValue(SelectedItemProperty, value);
}
public static string GetSelectedItem(UIElement element) {
return element.GetValue(SelectedItemProperty);
}
}
<TreeView c:TreeViewProperties.SelectedItem=“{Binding SelectedImage}” />
• Use Case – You want to add drag-n-drop functionality
to ItemsControl/Selector elements you’re using.
• Solution 1: Create a view for holding the elements, and
implement drag-n-drop by settings properties,
subscribing events and calling methods directly or
source/target in the view’s code behind.
• Solution 2: Create custom ListBox, ListView,… DataGrid
controls and implement drag-n-drop on each.
• Solution 3: Use attached properties to attach drag-ndrop behavior with any ItemsControl/Selector instance.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
41
• You can simply use a static class with several attached
properties as shown below.
• The disadvantage of using a static class is that each
state requires an attached property.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
42
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
43
• Microsoft Expression Blend 3 introduces behaviors,
which are reusable pieces of packaged code, based on
Attached Properties, that can be dragged onto any
object, and then fine-tuned by changing their
properties.
• Behaviors allow you to add interactivity to your
applications without having to write any code.
• Blend 3 attached behavior comes in two flavors:
– Triggers and Actions
– Behaviors
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
44
• You can think of triggers and actions as cause-andeffect relationships.
• A Trigger reacts to the cause and invokes one or more
Actions.
• Trigger is an object that listens for a specific condition,
such as an event or a property change, and invokes one
or more associated Actions.
• Triggers are extensible, so you can create custom
triggers.
• An Action is an object that can only do something.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
45
• To develop custom triggers and actions, first you
should have Blend 3 or Blend 3 SDK installed
• Second you have to add reference to:
System.Windows.Interactivity
• The assembly above is part of Blend 3 SDK.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
46
• To implement a
trigger, simply
create a class
which derives
from
TriggerBase<T>
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
47
• To implement an action, simply create a class which derives from
TriggerAction<T>
• You can implement a custom action that targets different object
using TargetedTriggerAction<DependencyObject>
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
48
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
49
• A Behavior can act without any external notification
from a Trigger or a Trigger-like item.
• While some condition needs to be met, it doesn't have
to be invoked by a Trigger.
• One way to allow users to
customize the functionality of your
Behavior is to expose Commands
as properties of the behavior.
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
50
• To implement a
behavior, simply
create a class
which derives
from Behavior<T>
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
51
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
52
Separated presentation patterns
cleanly separate out the visual portions
of your application from the business
and presentation logic portions.
Separating view from business provides
and easy way for unit testing
MVVM is a popular pattern especially
for WPF and SL.
Having a clean separation allows:
Developers to focus on application logic
Designers to focus on visual aspects
Unit test independently