WPF & Silverlight

Download Report

Transcript WPF & Silverlight

Creating rich applications
using
Model View ViewModel
David Ross
http://www.pebblesteps.com
Presentation Highlights
 Introduction to WPF/Silverlight
 Event based development
 Data binding
 Templates
 Presentation Patterns
 Testing
 Useful frameworks and Tools
WPF
 Fast GUI framework that uses the DirectX games
engine for rendering
 Part of Windows Vista but back ported to XP (features
such as transparency, shadows, pixel shaders etc work
poorly on that platform)
 Mature technology – Now version 3 (3.0, 3.5, 4.0)
 WPF cycle linked to Visual Studio releases/Service
Packs
Silverlight
 Browser plugin - Yearly release cycle (V5 in beta)
 Originally a cut down version of WPF but due to
release cycle often gets features before WPF
 Development platform for Windows Phone 7
 Out of Browser mode makes it look like a WPF
App/can run outside of the sandbox
 All communication with the server is via asynchronous
methods – Blocking operations would crash the
browser
Comparison to Windows Forms
 WinForms follow the underlying Windows GDI model
 Every item on the screen that can accept a mouse action is a
Window i.e. One screen might have 100 Windows
 Controls are responsible for their rendering
 Not extensible
 WPF/Silverlight is a complete rewrite and bypasses GDI
 One screen for the entire App
 All visual elements can accept mouse clicks – Everything is a
Button
 Rendering/Visualisation of ANY control is overrideable
 All controls can have other controls embedded inside them –
Everything is a Panel
 Data Binding works!
Development
 XAML – Extensible Application Markup Language
 XML based programming language
 Used to create a tree of objects (must have parameter
free constructors)
 Used to describe the Scene Graph in WPF and the
Workflow steps in Windows Workflow Foundation
 Code behind in any .NET language (C#, VB.NET, F#
etc)
Dependency Properties
 A Control may have hundreds of properties (Font,
Height, Width, Transparency etc)
 To save memory Controls of the same type SHARE the
same memory for properties (Flyweight pattern )
 When you set a Property (XAML, programmatically)
you override the shared default value
Attached Properties
 DependencyProperties include runtime magic to
override defaults
 Extended to allow Properties to be added/removed
from a Control at run time
 A control sitting inside a Grid is given attached
properties for the Column and Row it should sit within
 <Rectangle Grid.Row="1" Grid.RowSpan="6" Fill="#73B2F5"/>
 Hence Parent can iterate over child controls and check
if they have used an Attached Property to override the
defaults
Layout Panels
 Grid Panel
 Items are placed into columns and rows
 Items can span across columns and rows
 Stack Panel
 Appends items either horizontally and vertically after one
another
 Good for displaying items of different sizes
 Canvas – Used for (X, Y) positioning i.e. games or graphs
 Wrap Panel – Items are placed after each other and then
wraps
 Dock Panel – Winform like docking
Building pages with Events
 Windows Form and classic ASP.NET development style
 Events bubble up until they either are discarded or are used
<Window
x:Class="EventBasedDevelopment.MainWindow“
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TextBlock Name="Result" Text="Hello World"/>
<Button Click="ButtonAClick">Click me</Button>
<StackPanel Button.Click ="ButtonBClick">
<Button>Click me</Button>
</StackPanel>
</StackPanel>
</Window>
Code behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ButtonAClick(object sender, RoutedEventArgs e)
{
Result.Text = "Clicked by button A";
}
private void ButtonBClick(object sender, RoutedEventArgs e)
{
Result.Text = "Clicked by button B";
}
}
Result
Data Binding
Instead of manually changing the text after a mouse click WPF can
do it automatically
 Almost everything can be data bound from setting the Text on a
control, to its height, visibility, font, colour etc
 Types
 One Time – Value is read off the object once when the Control is
first created
 One Way – Value is read off the object each time it changes
 Two Way – Value that has been changed on the GUI is pushed to
the object
 One Way To Source – GUI can change object, but object can’t
change GUI
Only works with Properties public fields can’t be bound to
Data Binding example
<Window
x:Class="SimpleDataBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel Name="Panel">
<TextBlock Text="{Binding Path=Color}" Background="{Binding
Path=ColorBrush}"/>
<Button Click="Green_Click">Make Green</Button>
<Button Click="Blue_Click">Make Blue</Button>
<Button Click="Red_Click">Make Red</Button>
</StackPanel>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
Color = Colors.Purple;
DataContext = this;
InitializeComponent();
}
private void Green_Click(object sender, RoutedEventArgs e)
{
Color = Colors.Green;
}
private void Blue_Click(object sender, RoutedEventArgs e)
{
Color = Colors.Blue;
}
private void Red_Click(object sender, RoutedEventArgs e)
{
Color = Colors.Red;
}
public Color Color { get; set; }
public Brush ColorBrush
{
get { return new SolidColorBrush(Color); }
}
}
Kinda Works
 Buttons that are
clicked don’t update
the Textbox
 WPF uses the
Observer pattern
 We didn’t notify
WPF that the
properties had been
modified
INotifyPropertyChanged
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
...
public event PropertyChangedEventHandler PropertyChanged;
private Color _color;
public Color Color
{
get { return _color; }
set
{
_color = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Color"));
PropertyChanged(this, new PropertyChangedEventArgs("ColorBrush"));
}
}
}
}
INotifyPropertyChanged
 For WPF Data Binding to work in a OneWay or
TwoWay scenario any changes to an object are
announced with an event
 Instead of using List<T> use an
ObservableCollection<T> announces when items are
added or removed from the collection
 You need to fire an event for each property that has
become dirty after an action i.e. A First Name change
will also dirty Full Name
Replace string with Expression
 PropertyChanged(this, new
PropertyChangedEventArgs("Color"));
 If I rename Color to Colour and don’t update the string
the controls wont be notified/updated
 Common pattern is to use an Expression tree and a
shared base class for data objects
 RaisePropertyChanged(() => Color);
 The Expression is then converted into a string
Removing the plumbing with AOP
 Aspect Orientated Programming is used to remove
duplicate code that “crosses concerns” i.e. Security,
Logging, PropertyChangedEvents
 Available in Inversion of Controls Containers (Castle,
Spring.NET, Ninject, Unity etc) and Assembly rewriters
(PostSharp)
 Use an Interceptor to grab the call to object.Property = X
and replace with:
 object.Property = X
 PropertyChanged(this, “Property”)
 Code can then be “simplified” back to a C# Auto property
ICommand – Smarter events
 We also use Data Binding for calling methods
 Properties
 CanExecute – Returns a Boolean to indicate whether a
method can be called
 Execute – Delegate that is executed by WPF when the action
occurs
 CanExecuteChanged – Used to tell WPF that the command
is or isn’t available
 Hence we can turn functionally on and off easily
 Events can be moved out of the code behind and into the
Data Bound object which is probably modified by the
action anyway
IValueConverter
 The types exposed in our Data Bound object may not
be viewable
 A true/false flag may mean different panels are visible
on an entry screen
 A negative number may indicate the account is in
overdraft and it should be Red
Boolean to Visibility Converter
public class BooleanToVisibilityValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo
culture)
{
if (!(value is bool))
return null;
if ((bool)value)
return Visibility.Visible;
return Visibility.Hidden;
}
public object ConvertBack(object value, Type targetType, object parameter,
CultureInfo culture)
{
throw new NotImplementedException();
}
}
<Window x:Class="SimpleBooleanConverter.MainWindow“
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:System="clrnamespace:System;assembly=mscorlib" xmlns:SimpleDataBinding="clrnamespace:SimpleDataBinding" Title="MainWindow" Height="350" Width="525">
Make the converter
available
<Window.Resources>
<SimpleDataBinding:BooleanToVisibilityValueConverter x:Key="blnToVis"/>
<System:Boolean x:Key="PlaysCricket">False</System:Boolean>
<Style TargetType="TextBlock">
<Setter Property="Width" Value="150"/>
</Style>
</Window.Resources>
XAML as a factory
<StackPanel>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
Bool in the XAML
<TextBlock>How old are your?</TextBlock>
scope is passed to the
<TextBox Name="Age"/>
converter
</StackPanel>
<StackPanel Visibility="{Binding Source={StaticResource PlaysCricket},
Converter={StaticResource blnToVis}}">
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<TextBlock>Are you a bowler?</TextBlock>
<ComboBox>
<ComboBoxItem>No</ComboBoxItem>
<ComboBoxItem>Fast</ComboBoxItem>
<ComboBoxItem>Spin</ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<TextBlock>Are you a batsman?</TextBlock>
<ComboBox>
<ComboBoxItem>No</ComboBoxItem>
<ComboBoxItem>Yes</ComboBoxItem>
</ComboBox>
</StackPanel>
</StackPanel>
</StackPanel>
Data Templates
 We have a list<Animal> or
ObservableCollection<Animal> is the collection
elements can change
 The list includes instances of Cat, Dog, Horse wouldn’t
it be nice if we could display different sets of controls
for each of the different types of Animal as each has
different attributes
<Window
x:Class="DataTemplateAnimals.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:DataTemplateAnimals="clr-namespace:DataTemplateAnimals"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type DataTemplateAnimals:Cat}">
<WrapPanel>
<TextBlock>I am a happy kitty.</TextBlock>
<TextBlock>Lives left:</TextBlock>
<TextBlock Text="{Binding Path=LivesLeft}"/>
</WrapPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type DataTemplateAnimals:Dog}">
<WrapPanel>
<TextBlock>I am a doggy.</TextBlock>
<TextBlock>I bark this much:</TextBlock>
<TextBlock Text="{Binding Path=BarkVolume}"/>
</WrapPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Path=Animals}"></ListBox>
</Grid>
</Window>
public partial class MainWindow : Window
{
public ObservableCollection<Animal> Animals { get; set; }
public MainWindow()
{
Animals = new ObservableCollection<Animal>
{
new Dog {Age = 5, AgeInAnimalYears = 30, BarkVolume = 3},
new Cat {Age = 5, AgeInAnimalYears = 30, LivesLeft = 7}
};
DataContext = this;
InitializeComponent();
}
}
ControlTemplate
 Allows you to change the visual tree of a Control
 Thus allows everything to be changed
 How it looks
 How it deals with events
IDataErrorInfo



In the data binding setup turn on validation
User edits still populates the bound object
Only allow a Save operation was the validation succeeds
class Example : IDataErrorInfo
{
public int Age {get; set;}
public string Error {get; private set;}
public string this[string name]
{
get {
if(name = “Age”){
if(Age>120 || Age < 18) return “Must be over 18”;
}
return null;
}
}
Triggers
 WPF only
 A change to a property on a bound object can automatically
trigger a visual change such as using a different Style
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BitmapEffect">
<Setter.Value>
<OuterGlowBitmapEffect GlowColor="Gold" GlowSize="10" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
Storyboard
 Time line of changes that are made to an object that
can be programmatically kicked off
 Button fades in and out after a mouse over
 Labels become textboxes when moving into edit mode
 Animation are easy
 set the frame rate
 set the start and end position
 set the duration for the move
Visual State Manager
 Silverlight 2.0 and then ported to WPF 4.0
 Control is a state machine
 Each state can have a different visual look – i.e. Button is
enabled, disabled, has focus, clicked etc
 Storyboard used to define the look of a state and how
you move between the states
 Microsoft Blend is the best tool to create Storyboards
and to define different visual states for the controls
User Controls
 Used in 99% of cases
 Inherits from UserControl
 Define the look and feel/capability of the control by
adding Child Elements to it
 Can use custom DependencyProperties to customise
behaviour but typically use Data Binding instead
 No ability to change the layout
Custom Controls
 Inherits from Control
 Custom DependencyProperties used so that the
control’s behaviour can be modified in the properties
window
 Define a ControlTemplate for layout and to include
child controls
 Used for creating Calendar controls etc where the end
user may want to customise the layout or rendering
Presentation Patterns
Used to separate the concerns of showing the data,
editing the data and processing the user’s interactions
 Model View Controllers i.e. ASP.NET MVC, MFC,
Struts, JSF
 Model View Presenter i.e. Winform CAB, ASP.NET
MVP
 Model View ViewModel i.e WPF & Silverlight best
practice
What is the Model?
 Its all the information that the user is interacting with
 Usually reaches user after going through a service on a
server
 It should mirror (model) the problem domain
 Often hierarchal
 Often needs to be consistent i.e. Saving a model that is
partially populated will fail
What is the View?
 The “stuff” that is visible to the user
 Responsible for presentation only
 Displays the model but data editing/transforming is
delegated to another component
MVC
 Controller handles the HTTP request, populates a model
and determines which View to display the results
 Repeat…
*
View
1
Controller
Model
MVP
 In ASP.NET MVC a view is (re)created each request
 In MVP the View sticks around i.e thick client or
session/view state
 Event based
 Presenter listens to changes on the View
 View accesses Model data via Presenter
View
1
1
Presenter
Model
MVVM
 MVP but with the benefits of using Data Binding
hence ViewModel doesn’t need to listen to events from
the View
 ViewModel doesn’t “know” about the View so we can
easily unit test presentation logic (by faking out the
view)
View
*
1
ViewModel
Model
What is the ViewModel
 Wraps the Model
 Collapses complex object graph into a flat structure
 Simplifies the view by Aggregating and Retrieving i.e. Instead
of transversing through a tree the ViewModel does it
 Implements interface INotifyPropertyChanged
 Informs the View to redraw/update itself
 ViewModel can have other ViewModels as properties
 Each region on the screen can be a ViewModel
 Detail views etc
 Can be inconsistent domain wise i.e. ViewModel can be
populated with incomplete or badly formed data. Once
correct populate the Model
ViewModel versus Converter
 A ViewModel may be displayed by many Views
 Hence it an be frowned upon having properties that
expose Visual elements
 Brushes, Visibility, Animation Storyboards etc
 Converters can act as bridge between the View and the
ViewModel
Note: This rule/pattern is REGULARLY broken i.e. expose
a Brush if you have only one View and refactor to
converter when required
Data Templates and ViewModels
 Where the magic happens
 Data Template is a View factory that uses an Object Type as
the Key
 Parent ViewModel exposes other ViewModels as properties
and DataTemplate automatically finds the View to display
 A PageViewModel may have properties for different visual
regions
 A region can be changed just by replacing a property with a
different ViewModel
 Implies 90% of the time there is a single View per
ViewModel
DataTemplate - Wizards
 User is presented with a chain of screens whose contents




depends on the answer of the previous page
Back button must work and if user changes their mind and
causes the navigation direction to change the answers on
the pages must disappear
WizardViewModel manages the screen layout and
navigation
Use a Stack to store User responses that can be popped on
and off as the screen changes
Have a CurrentScreen property/state machine so that the
DataTemplate can automatically choose the correct screen
Testing
 ViewModel includes all the “logic” but doesn’t interact with a
View directly – Only notifies
 Easy to create a Unit test that changes Properties etc and then
verify the results
To check if the Save button is only enabled once all text boxes
are populated
 Create ViewModel
 Listen for the SaveCommand.CanExecuteChanged event
 Assert SaveCommand.CanExecute is false
 Populate ViewModel input properties
 Assert that SaveCommand.CanExecuteChanged fired
 Assert SaveCommand.CanExecute is true
Shared WPF & Silverlight
development
 Silverlight is asynchronous only
 Cut down version of the .NET framework
 Write a single set of C# files that are included in both a
Silverlight and WPF assembly
 Patterns and Practices team have written “Project
Linked” that automatically links the files of one project
to another each compile
 Use pre-processor exclude WPF only code
 #if !SILVERLIGHT
Tools - Snoop
 Allows developer to see the Scene Graph of any WPF
application
 Almost impossible to debug errors where Control
doesn’t appear correctly out of a DataTemplate without
it
Tools - Blend
 Tool used by Designers to create the look and feel for
an application
 Built in support for drawing, animations and Visual
State Manager
 Blend and Visual Studio share C#, Project and
Solution files hence designers and developers work
together
Design Mode & Blendability
 When a ViewModel is constructed it can check if the
application is running inside Visual Studio or Blend
 By creating “fake” data and correctly populating all of
the properties the View will then render a fully
working populated screen
 Allows Designers to easily style a page
What do frameworks offer
Caliburn.Micro
 Convention over Configuration
 No data binding elements in XAML instead Data Binding happens at runtime
based on a set of conventions
 Button called Authorise will be automatically bound to a command called
AuthoriseCommand
 Screen Lifecycle management
 Ability to stop application quitting if there is unsaved work
 Event Aggregator
 Publish-Subscribe infrastructure that allows Views or ViewModels to publish
events and have a completely unrelated component subscribe
 Coroutines
 Allows developer to build a state machine that will continue at a set execution
point i.e. Once an asynchronous operation has completed restart here. Based
on IResult.
 Makes to it easy to create screen flows that don’t share data
What do frameworks offer
Managed Extensibility Framework
 Plugin architecture that allows new components (in the form of
binaries) to be added to a solution by placing them into a plugin
folder
 In Silverlight allows different application components to be
hosted in different files to make initial application loading faster
Prism
 Patterns and Practices for Microsoft
 Port of the WinForm framework to WPF
 Was created before Model View ViewModel pattern became
prevalent closer to Model View Presenter
 Can be overly complex
Questions