WINDOWS
PRESENTATION FOUNDATION
Introduction to Windows Presentation
Foundation
Overview
The Windows
Presentation Foundation is Microsofts next generation UI framework to create
applications with a rich user experience. It is part of the .NET framework 3.0
and higher.
WPF combines
application UIs, 2D graphics, 3D graphics, documents and multimedia into one
single framework. Its vector based rendering engine uses hardware acceleration
of modern graphic cards. This makes the UI faster, scalable and resolution
independent.
The followinig
illustration gives you an overview of the main new features of WPF
Separation of Appearance and Behavior
WPF separates the
appearance of an user interface from its behavior. The appearance is generally
specified in the Extensible Application Markup Language (XAML), the behavior is implemented in a
managed programming language like C# or Visual Basic. The two parts are tied
together by databinding, events and commands. The separation of appearance and
behavior brings the following benefits:
- Appearance and behaviour are
loosely coupled
- Designers and developers can work
on separate models.
- Graphical design tools can work
on simple XML documents instead of parsing code.
1.
LOOK AND FEEL CHANGE BY USING WPF
2.
IN THIS WE
USE XAML LANGUAGE
3.
IT SOLVE
THE PROBLEM OF RESOLUTION WHICH IS THE MAIN PROBLEM IN WINDOW BASED APPLICATION.
THE
CONTROLS VIEW(POSITION) IS ALWAYS CHANGED AT ANOTHER RESULTION SYSTEM THAT IS
THE MAIN PROBLEM OF WINDOW BASED APPLICATION WHICH IS SOLVED BY WPF
Ø IT COMES IN .NET FRAMEWORK 3.0
Ø WPF IS THE ALTERNATIVE FRAMEWORK INTODUCED BY
MICROSOFT TO SOLVE THE PROBLEM OF WINDOW BASED APPLICATION
Ø IT USE THE DEVICE INDEPENDENT MASURMENT IN
UNIT(INCHES) NOT IN PIXLES AS IN WINDOW FORM APPLICATION
Ø THERE IS NO ANY FEATURE IN WINDOW BASED APPLICATION TO
USE HARDWARE DEVICE(GUI) RESOURCE
ACCELERATION, WHICH IS NOW WPF. WPF APPLICATION ARE CREATED USING
HARDWARE GRAPHICS ACCELERATION WHICH MAKE APPLICATION SO SMOOTH AND SHARP AND
IT AUTOMATICALLY DETECT THE HARDWARE CONFIGURATION AND RANDER ACCORDING TO THE
HARDWARE ACCELERATION(GUI) FEATURES
Ø IF WE TAKE THE EXAMPLE OF WEB BASED APPLICATION OUR
PRESENTATION LOGIC AND BUSINESS LIGIC ARE IN SEPERATE-2 FILES. WHICH MAKES IT
EASY TO IMPLEMENT AND TO CONFIGURE. AND WHICH HELPS TO DO WORK PROGRAMMER
SEPERATELY ON DIFFERENT -2 FILE, THAT IS NOT
IN WINDOW BASED APPLICATION BUT NOW IN WPF THERE IS SEPARATE-2 FILES FOR
DESIGING AND FOR CODING LIKE WEB BASED
APPLICATION WHICH HELPS THAT DESIGNER CAN DO IT’S WORK SEPERATELY TO THE
PROGRAMMER.
Ø IN WPF A LANGUAGE IS LAUNCHED CALLED XAML IN WHICH WE
CAN WRITE OUR PRESENTATION CODE IN A DECLARATIVE WAY LIKE ASP
Ø AND THIS XAML
IS ALSO USED IN SILVERLIGHT ALSO
Ø A WPF APPLICATION CAN ALSO RUN ON A DESKTOP SYSTEM AS
WELL AS CAN RUN ON BROWSER ALSO MEAN BY HTTP PROTOCOL. BUT IT SUPPORT ONLY
INTERNET EXPLORER MEANS CAN RUN ONLY IN INTERNET EXPLORER THAT’S CALL X-WEB,
BUT IT HAS SOME LIMITATION THAT’S WHY MICROSOFT INRODUCE SILVERLIGHT TO CREATE
WEB BASED APPLICATION
Ø IN WEB SITE WE USE STYLESHEET TO KEEP OUT DESIIGNING
RESOURCE IN A SEPARATE FILE WHICH IS NOT IN WINDOW BASED APPLICATION, BUT NOW
WE CAN KEEP OUR DESIGN RESOURCE LIKE STYLE SHEET IN WPF APPLICATION, WE CAN
STORE OUR CONTROL DESIGN SETTINGS IN RESOURCES TO APPLY IT ON MULTIPLE CONTROLS
Ø IN WINDOW FORM APPLICATION TO USE DRAWING FEATURES WE
HAVE TO USE DDI AND GDI, BUT NOW IN WPF IT IS ESAY BY XAML
Ø IN WPF WE CAN ALSO CREATE CHILD CONTROL OF CONTROLS,
MEANS HERE EACH CONTROL WORK AS AN CONTAINER FOR ANOTHER CONTROL AND IT IS DONE
BY XAML
Ø TO CREATE ANIMATION IS SO DIFFICULT IN WINDOW BASED
APPLICATION BUT NOW IT IS SO EASY TO CREATE ANIMATION IN WPF BY XAML
Ø MEDIA SUPPORT IS ALSO COME IN WPF WITH ADVANCE
FEATURES MEANS WE CAN PLAY SONGS, AND MOVIES ALSO.
Ø IN WPF A FEATURE IS ALSO COME WHICH IS SO
POWERFUL RATHER THAN WINDOW THAT IS
BINDING , WHICH USE DEPEDENCY PROPERTIES IN WHICH WE CAN CREATE DEPEDENCY OF
CONTROLS ON ANOTHER CONTROLS
Ø IN WPF THERE IS ALSO COME A POWERFULL FEATURE WITH
MVVM, IN WHICH WE CAN DEAL MULTIPLE VIEWS FROM A SINGLE LOCATION BECAUSE THEY
ARE LOOSLY COUPLED, WHERE AS IN WINDOW BASED APPLICATION THEY ARE TIGHTLY
COUPLED
Ø IN WPF MAIN CONTAINER IS WINDOW OBJECT IS THE ROOT
OBJECT AND IN WINDOW OBJECT WE CAN KEEP ONLY A SINGLE CHILD CONTROL
Ø PANNEL CONTROL CAN KEEP MULTIPLE CONTROLS
Ø IN WEB PAGE THERE IS CONCEPT OF EVENT BUBBLING MEANS
EVENT OF CHILD CONTROLS CAN BE HANDLED BY IT’S PARENT CONTROLS
Ø IN WPF APP.XAML IS SAME AS PROGRAM.CS WHICH IS IN
WINDOW BASED APPLICATION MEANS WHICH MUST BE RUN AT FIRST TO SET IT
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
Ø TO SEE CODE PART JUST DO RIGHT CLICK ON YOUR XAML PAGE
AND SELECT VIEWCODE
FILE >>>>NEW
PROJECT >>>>> VISUAL C#>>>> WPF APPLICATION
wpf
1.
Panel
2.
Gradients
3.
Brushes
4.
Triggers
5.
Setter
6.
Binding
7.
Property
8.
Animation
Start a wpf
application
1.pannel
Panel are
just containers
1.
Grid
GRID IS THE
LAYOUT PANNEL AND MOST IMPORTANT WHICH WORK SAME AS A TABLE
Grid is the
most flexible panel to move the control flexibly, than thIs is best to do so,
we can arrange the position of controls easily,
DOCK PANEL
CONTROLS CAN BE FIX AT LEFT, RIGHT, TOP AND
BOTTOM SIDE LIKE MENU BARS ALWAYS ON TOP
AND STATUS BAR ALWAYS AT BOTTOM
WRAP PANNEL
And if we have the controls more than
the height of the page than your next controls wrap panel it will places it in
the next line, WHEN SPACE IS FINISH IT AUTOMATICALLY SHIFT IT TO IN ANOTHER LINE
CANVAS
IN CANVAS
WE CAN KEEP OUR CONTROL ANY WHERE ACCODING TO THE POSITION, CORDINATES
1GRID
WE CAN ALSO
CREATE COLUMN AND ROWS SIMPLY MOUSE JUST CLICK OUT SIDE OF THE PAGE TO CREATE
COLUMN AND ROWS, AND WE CAN ALSO ADJUST THEM ACCODING TO OUR MEASURMENTS THAN
IT WILL CREATE XAML CODE OWNSELEF
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="58*" />
<RowDefinition Height="126*" />
<RowDefinition Height="127*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="214*"
/>
<ColumnDefinition Width="148*"
/>
<ColumnDefinition Width="141*"
/>
</Grid.ColumnDefinitions>
</Grid>
We can also
create it by own self by writing simple xaml code
<Grid.RowDefinitions>
<RowDefinition Height="100"></RowDefinition>
<RowDefinition Height="100"></RowDefinition>
<RowDefinition Height="100"></RowDefinition>
</Grid.RowDefinitions>
We can also
give the height in value as above and we can also give the height and width in
* means which is eqal to % as below
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="2*"></ColumnDefinition>
</Grid.ColumnDefinitions>
We can also
give the background color
<Window x:Class="WpfApplication1.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" Background="Aqua">
To give background color of a grid
<Grid Background="Yellow">
We can
also give margin in grid
<Grid Margin="10,5,5,5" Background="Yellow">
By default
position of your controls Is in firstrow and first column if we create a
control outside of the column androw definition
</Grid.ColumnDefinitions>
<Button Content="submit" Height="50" Width="150"></Button>
</Grid>
We can also
give the exact row-column position of a
control by xaml
<Button Grid.Row="0" Grid.Column="0" Content="submit" Height="20" Width="150"></Button>
<TextBox Grid.Row="0" Grid.Column="1" Text="adfads" Height="20" Width="120"></TextBox>
We can also give the margin of our
grid
<Grid Margin="10,5,5,5" Background="Yellow">
If we want that the height of a row is adjust automatically
according the height of controls
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
And if you want to create a event of a controls than enter
click and press tab to generate handler
<Button Click="Button_Click" Grid.Row="0" Grid.Column="0" Content="submit" Height="20" Width="150"></Button>
<TextBox Grid.Row="0" Grid.Column="1" Text="adfads" Height="20" Width="120" Name="t1"></TextBox>
Than right click and
select view code to see your code part
private void
Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("hello
how are you");
MessageBox.Show(t1.Text);
}
STACK PANEL
IN STACK
PANNEL CONTROLS ARE ARRANGED IN A SEQUENCE LIKE A STACK
But If we
want to create controls at run time, than we have to give some coordinates,
than it overlap all controls at the same coordinates, and we can do this by
using stack panel control
But stack
panel is not so good in the case if we have lot of in number controls than it
will increase the height continuously,
<StackPanel Height="300" Background="Aqua">
<Button Height="30" Width="120" Content="button1"></Button>
<Button Height="30" Width="120" Content="button1"></Button>
<Button Height="30" Width="120" Content="button1"></Button>
<Button Height="30" Width="120" Content="button1"></Button>
<Button Height="30" Width="120" Content="button1"></Button>
</StackPanel>
We can also
give the position of our controls
<StackPanel Height="300" Background="Aqua">
<Button HorizontalAlignment="Left" Height="30" Width="120" Content="button1"></Button>
<Button Height="30" Width="120" HorizontalAlignment="Left" Content="button1"></Button>
</StackPanel>
We can also
give the orientation of our stack
<StackPanel Height="300" Orientation="Horizontal" Background="Aqua">
<Button HorizontalAlignment="Left" Height="30" Width="120" Content="button1"></Button>
<Button Height="30" Width="120" HorizontalAlignment="Left" Content="button1"></Button>
</StackPanel>
WRAP PANNEL
And if we
have the controls more than the height of the page than your next controls wrap
panel it will places it in the next line, WHEN SPACE IS FINISH IT AUTOMATICALLY
SHIFT IT TO IN ANOTHER LINE
<WrapPanel Height="300" Orientation="Horizontal" Background="Aqua">
<Button HorizontalAlignment="Left" Height="30" Width="120" Content="button1"></Button>
<Button Height="30" Width="120" HorizontalAlignment="Left" Content="button1"></Button>
<Button Height="30" Width="120" HorizontalAlignment="Left" Content="button1"></Button>
<Button Height="30" Width="120" HorizontalAlignment="Left" Content="button1"></Button>
<Button Height="30" Width="120" HorizontalAlignment="Left" Content="button1"></Button>
</WrapPanel>
IN WPF EACH CONTROL IS WORK AS A CONTAINER MEANS
WE CAN KEEP A CONTROLS IN TO A ANOTHER CONTROL IN CONTENT AND THIS CONTROL
FURTHERE WORK AS A CONTAINER FOR THE
SECOND CONTROL
<WrapPanel Height="300" Orientation="Horizontal" Background="Aqua">
<Button HorizontalAlignment="Left" Height="30" Width="120">
<Button.Content>
<StackPanel Orientation="Horizontal">
<Label Content="play"></Label>
<Image Source="image\Sunset.jpg" Height="20" Width="30"></Image>
</StackPanel>
</Button.Content>
</Button>
<Button Height="30" Width="120" HorizontalAlignment="Left" Content="button1"></Button>
<Button Height="30" Width="120" HorizontalAlignment="Left" Content="button1"></Button>
</WrapPanel>
To decide which form will run open app.xaml
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml">
CANVAS
IN CANVAS
WE CAN KEEP OUR CONTROL ANY WHERE ACCODING TO THE POSITION, CORDINATES
<Canvas Background="AliceBlue" Margin="20">
<Rectangle Height="100" Width="150" Fill="Red" Canvas.Top="20" Canvas.Left="30"></Rectangle>
<Ellipse Height="100" Width="150" Fill="Green" Canvas.Top="40" Canvas.Left="50"></Ellipse>
</Canvas>
if you want that
which control will be shown on back side of the another control then send it’s
panel.zindex=2
Panel.ZIndex="2"
<Rectangle Panel.ZIndex="2" Height="100" Width="150" Fill="Red" Canvas.Top="20" Canvas.Left="30"></Rectangle>
<Ellipse Height="100" Width="150" Panel.ZIndex="1" Fill="Green" Canvas.Top="40" Canvas.Left="50"></Ellipse>
DOCK PANEL
CONTROLS CAN BE FIX AT LEFT,RIGHT,TOP AND
BOTTOM SIDE LIKE MENU BARS ALWAYS ON TOP
AND STATUS BAR ALWAYS AT BOTTOM
<DockPanel Background="AliceBlue">
<Button Height="30" Content="submit" DockPanel.Dock="Top"></Button>
<Button Content="submit" DockPanel.Dock="Left"></Button>
<Button Content="submit" DockPanel.Dock="Right"></Button>
<Button Height="30" Content="submit" DockPanel.Dock="Bottom"></Button>
<Button Content="fill"></Button>
</DockPanel>
Now we will
discuss about resources which work same as stylesheet in web
<StackPanel>
<Button Height="30" Width="80" FontSize="15" Foreground="Yellow" Background="red" Content="submit"></Button>
<Button Height="30" Width="80" FontSize="15" Foreground="Yellow" Background="red" Content="submit"></Button>
If you see
above same style is apply on these buttons we can escapes to rewrite of these
style setting by using resource so just create resources file and then apply on
any controls
<Window.Resources>
<Style x:Key="btnstyle" TargetType="Button">
<Setter Property="Foreground" Value="yellow"></Setter>
<Setter Property="FontSize" Value="18"></Setter>
<Setter Property="Background" Value="red"></Setter>
</Style>
</Window.Resources>
<StackPanel>
<Button Height="30" Width="80" Style="{StaticResource btnstyle}" Content="submit"></Button>
<Button Height="30" Width="80" Style="{StaticResource btnstyle}" Content="submit"></Button>
<Button Height="30" Width="80" Style="{StaticResource btnstyle}" Content="submit"></Button>
<Button Height="30" Width="80" Style="{StaticResource btnstyle}" Content="submit"></Button>
</StackPanel>
If you want
to apply and create a style sheet for a particular control and don’t
want to create a key then
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Foreground" Value="yellow"></Setter>
<Setter Property="FontSize" Value="18"></Setter>
<Setter Property="Background" Value="red"></Setter>
</Style>
</Window.Resources>
<StackPanel>
<Button Height="30" Width="80" Content="submit"></Button>
<Button Height="30" Width="80" Content="submit"></Button>
<Button Height="30" Width="80" Content="submit"></Button>
<Button Height="30" Width="80" Content="submit"></Button>
</StackPanel>
And if you want that this style sheet must not
be apply in a single controls between
more than on e control then
<Button Height="30" Style="{x:Null}" Width="80" Content="submit"></Button>
</StackPanel>
In wpf we
can create one or more than one style sheet for a particular controls and can
inherit the a style sheet to another style sheet mean resource
<Window.Resources>
<Style x:Key="btnstyle" TargetType="Button">
<Setter Property="Foreground" Value="yellow"></Setter>
<Setter Property="FontSize" Value="18"></Setter>
<Setter Property="Background" Value="red"></Setter>
</Style>
<Style x:Key="style2" BasedOn="{StaticResource btnstyle}" TargetType="Button">
<Setter Property="FontStyle" Value="italic"></Setter>
</Style>
</Window.Resources>
<StackPanel>
<Button Height="30" Width="80" Style="{StaticResource style2}" Content="submit"></Button>
<Button Height="30" Width="80" Style="{StaticResource style2}" Content="submit"></Button>
<Button Height="30" Width="80" Style="{StaticResource style2}" Content="submit"></Button>
</StackPanel>
And if you
want to create style sheet(resource file) which will be accessible by all the
pages of this wpf application then open
App.xaml and create your resource file in
application resource tag than it will be access by the controls simply just
passing it’s key name at all pages
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window2.xaml">
<Application.Resources>
<Style x:Key="btnstyle" TargetType="Button">
<Setter Property="Foreground" Value="yellow"></Setter>
<Setter Property="FontSize" Value="18"></Setter>
<Setter Property="Background" Value="red"></Setter>
</Style>
<Style x:Key="style2" BasedOn="{StaticResource btnstyle}" TargetType="Button">
<Setter Property="FontStyle" Value="italic"></Setter>
</Style>
</Application.Resources>
</Application>
And if you
want a control must chage it’s properties or colors behavior when a mouse is go
over than it’s controls than for it we have to create a trigger in style
sheet(resource file);
<Application.Resources>
<Style x:Key="btnstyle" TargetType="Button">
<Setter Property="Foreground" Value="yellow"></Setter>
<Setter Property="FontSize" Value="18"></Setter>
<Setter Property="Background" Value="red"></Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Foreground" Value="green"></Setter>
<Setter Property="FontSize" Value="19"></Setter>
<Setter Property="Background" Value="aliceblue"></Setter>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="style2" BasedOn="{StaticResource btnstyle}" TargetType="Button">
<Setter Property="FontStyle" Value="italic"></Setter>
</Style>
</Application.Resources>
Here WE CAN ALSO
CREATE RESOURCE DICTIONARY
ADD A NEW
ITEM>>> RESOURCE DICTIONARY
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="btnstyle" TargetType="Button">
<Setter Property="Foreground" Value="yellow"></Setter>
<Setter Property="FontSize" Value="18"></Setter>
<Setter Property="Background" Value="red"></Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Foreground" Value="green"></Setter>
<Setter Property="FontSize" Value="19"></Setter>
<Setter Property="Background" Value="aliceblue"></Setter>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="style2" BasedOn="{StaticResource btnstyle}" TargetType="Button">
<Setter Property="FontStyle" Value="italic"></Setter>
</Style>
</ResourceDictionary>
Than open a
app.xaml file and use this resource dictionary then it will automatically apply
on your allpages
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml">
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Than save
it and build your application.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
And if
YOUWANT TO CREATE A CONTROLS OF A ELLIPSE SHAPE THAN
<Window.Resources>
<Style x:Key="btn" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Fill="{TemplateBinding Background}" Stroke="{TemplateBinding BorderBrush}"></Ellipse>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center">
</ContentPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Button Click="Button_Click" Background="Yellow" BorderBrush="blue" Content="ducat" Height="30" Width="150" Style="{StaticResource btn}">
</Button>
</Grid>
</Window>
AND TO
APPLY AND TO USE IT
Brushes
First by
wizard
Right click on controls than click on
properties.
Location of
brushes always given in .point. from 0 to 1
And it has
two points startpoint and end point
Resource
dictionary
Resource
file
App.xml
file
Rich composition
Controls in WPF are
extremely composable. You can define almost any type of controls as content of
another. Although these flexibility sounds horrible to designers, its a very
powerful feature if you use it appropriate. Put an image into a button to
create an image button, or put a list of videos into a combobox to choose a
video file.
<Button>
<StackPanel
Orientation="Horizontal">
<Image
Source="speaker.png"
Stretch="Uniform"/>
<TextBlock
Text="Play Sound"
/>
</StackPanel>
</Button>
Highly customizable
Because of the strict
separation of appearance and behavior you can easily change the look of a
control. The concept of styles let you skin controls
almost like CSS in HTML. Templates let you replace the entire appearance of a control.
The following example
shows an default WPF button and a customized button.
Resolution independence
All measures in WPF
are logical units - not pixels. A logical unit is a 1/96 of an inch. If you
increase the resolution of your screen, the user interface stays the same size
- it just gets crispier. Since WPF builds on a vector based rendering engine
it's incredibly easy to build scaleable user interfaces.
Last modified: 2011-08-15
18:49:42
Copyright (c) by Christian Moser, 2011. How to create a simple WPF application
In Visual Studio 2008
Open Visual Studio
2008 and choose "File", "New", "Project..." in
the main menu. Choose "WPF Application" as project type.
Choose a folder for
your project and give it a name. Then press "OK"
Visual Studio creates
the project and automatically adds some files to the solution. A Window1.xaml
and an App.xaml. The structure looks quite similar to WinForms, except that the Window1.designer.cs file is no longer code but it's now declared
in XAML as Window1.xaml
Open the Window1.xaml file in the WPF designer and drag a Button and
a TextBox from the toolbox to the Window
Select the Button and
switch to the event view in the properties window (click on the little yellow
lightning icon). Doubleclick on the "Click" event to create a method
in the codebehind that is called, when the user clicks on the button.
Note: If you do not
find a yellow lightning icon, you need to install the Service Pack 1 for VisualStudio on your machine. Alternatively you can
doubleclick on the button in the designer to achieve the same result.
Visual Studio
automatically creates a method in the code-behind file that gets called when
the button is clicked.
private void button1_Click(object sender,
RoutedEventArgs e)
{
textBox1.Text = "Hello WPF!";
}
The textbox has
automatically become assigned the name textBox1 by the WPF designer. Set text Text to "Hello WPF!"
when the button gets clicked and we are done! Start the application by hit [F5]
on your keyboard.
Learn WPF in one Week
I started to build a one week training course to learn WPF. Starting with the basics and going through
the important concepts of the framework up to more complex topics. I hope you
like it.
Day 1 - Getting started
- Install the development tools
- Learn the basic concepts of WPF
- Create your first WPF application
- Learn how WPF changed the development workflow
Day 2 - Concepts of WPF
- Get
an introduction to XAML
- Learn about the hierarchical relation of
elements in WPF
- Find out about the magic behind
DependencyProperties
- Get familiar with routed events.
Day 3 - Layout and Controls
- Learn the layout basics
- See the grid layout panel in action
- Stack elements with the stackpanel
- Get an overview about the variety of included
controls.
- Have a look at 3rd-party libraries
Day 4 - DataBinding and UI Architecture
- Introduction to WPF DataBinding
- How to display, sort and filter data
- Using
the Model-View-ViewModel Pattern
- Learn how to validate user input
- Create your own ValueConverter
- Enhance the MVVM pattern by using Behaviors and
Actions
Day 5 - Templates and Styles
- Learn how to build rich user experience with WPF
- Style
the appearance of your controls
- Completely replace the look of a control
- How to display complex data in lists by using
DataTemplates.
Some of the articles
are not yet finished. The content for the subsequent days will follow soon...
:-)
MVVM(MODEL-VIEW-VIEW-MODEL)
WHAT IS
MVVM AND WHY WE USE IT
·
SEPERATION
PATTERN
SEPARATE
DESIGN/PRESENTATION LOGIC FROM BUSINESS LOGIC
·
SEPERATION
OF CONCERNS
·
TESTABLE
·
MAINTAINABLE
·
SCALABLE
·
What is MVVM?
·
Model-View-ViewModel (aka Presentation Model),
provides architectural solution for the Aplication with UI with complex
interdependent interactions.
·
Separate the UI(View) from the UI logic using a
ViewModel that encapsulates the interactions and provides properties for a View
to retrieve its state (and the state of its elements).
·
·
Why MVVM?
·
1. Separates UI from Model. If model needs to change, it can
without changing the view and vice versa.
·
2. Avoids duplicated code to update views.
·
3. Unit testable UI logic.
·
4. You can use a 'viewmodel' to aggregate parts of your model
that exist in separate classes/libraries to facilitate a more fluent interface
for the 'view' to deal with.
·
5. Data-binding support with INotifyPropertyChanged, ICommand
and IvalueConverters
·
6. Easy to refactor
·
7. Extensibility.
·
Important Note
Friends, I would very much appreciate if you leave me a line or
two in the comments section stating how you think this article can be improved
and what other topics on MVVM you want me to cover. Thanks.
Introduction
As many companies are switching from WinfForms to WPF/Silverlight,
several project managers recently asked me almost identical questions about
MVVM:
- What
is MVVM Pattern?
- What
are the advantages of the MVVM approach?
The purpose of this article is to answer these questions and to
explain the MVVM pattern in the simplest possible way.
I assume that the article readers have not had any previous
exposure to the MVVM pattern but have some knowledge of WPF or Silverlight.
Time permitting, I plan to write more MVVM articles which will
include comparison of different MVVM frameworks and introduce a new MVVM
framework.
MVVM Overview
Model-View-ViewModel (MVVM) pattern splits the User Interface code
into 3 conceptual parts - Model, View and ViewModel out of which the concept of
the ViewModel is the new and the most exciting.
- Model
is a set of classes representing the data coming from the services or the
database.
- View
is the code corresponding to the visual representation of the data the way
it is seen and interacted with by the user.
- ViewModel
serves as the glue between the View and the Model. It wraps the data from
the Model and makes it friendly for being presented and modified by the
view. ViewModel also controls the View's interactions with the rest of the
application (including any other Views).
ViewModel code can (and should) refer to the Model, but the Model
classes (if separate from the ViewModel) should not be aware of the ViewModel.
View should be aware of the ViewModel, but ViewModel should be not aware of the
View. In the diagram above, the arrows are showing which MVVM part is aware of
which.
Similar to the models in the older patterns, the Model within MVVM
pattern is simply data coming from the service or the database. Quite often,
the Model can be built to be part of the ViewModel. Because of that, in our
samples, we'll skip the model and concentrate primarily on the ViewModel, the
View and interactions between them.
WPF Concepts Related to the MVVM Pattern, Communications between
the View and the ViewModel
MVVM pattern became possible because of the following new concepts
that came into being as part of the WPF (and later Silverlight).
- WPF
Bindings - Each binding connects two properties (possibly on two different
objects) so that if one of them changes, the other changes too.
- WPF
Data Templates, which convert non-visual data (ViewModel) into its visual
representation (View).
- WPF
Commands (or Microsoft Expression Blend SDK interactivity behaviors) serve
to pass the events from the Views to the ViewModels.
WPF Bindings, WPF Commands and MS Expression Blend SDK
interactivity functionality provide the necessary plumbing for communications
between the View and the ViewModel. Another method can be employed for such
communications - C# events can be used to trigger a change within a View when
something happens within its ViewModel. This method should be avoided whenever
possible because it implies code behind within the view (to register an event
handler). Instead, one should use the bindings (perhaps combined with the
triggers) to pass information about changes within the ViewModel to the View.
Here is a diagram depicting different ways of communicating
between the View and the ViewModel:
When looking at this diagram, one might ask why the Binding and C#
Events arrows are pointing from the ViewModel to the View even though, as
stated above, the ViewModel is not aware of the View. The answer is that the
arrows on this diagram are pointing from an MVVM part that causes a change to
the part which receives the change. The Bindings are set within the View and
even though the ViewModel is not aware of the View, the changes to the
ViewModel still propagate to the View via the Bindings. In case of C# events,
the event handlers on ViewModel's events should also be set within the View's
code behind, so that the View functionality will trigger a change when changes
occur within the ViewModel.
WPF Bindings
Below is a short (and by no means comprehensive) overview of the
WPF bindings needed for understanding the MVVM pattern. For more information on
the bindings, try e.g. Data
Binding Overview, or Data
Binding in WPF or
plenty of other resources available on the internet.
WPF binding connects two properties (called binding target
property and binding source property), so that if one changes, the other
changes too. The target property of a binding should always be a WPF dependency
property (for the definition of a dependency property - check WPF tutorials).
The source property of a binding should be either a dependency property or fire
PropertyChanged
event on the property change.
A simple binding sample is located under "
BindingSample
"
solution. It displays student data (student first name and student grade point
average) within its window:
The student data is represented by an object of class
StudentData
. One can see that StudentData
has two properties: StudentFirstName
and StudentGradePointAverage
:public class StudentData : INotifyPropertyChanged
{
...
string _firstName = null;
public string StudentFirstName
{
get
{
return _firstName;
}
set
{
_firstName = value;
OnPropertyChanged("FirstName");
}
}
double _gradePointAverage;
public double StudentGradePointAverage
{
get
{
return _gradePointAverage;
}
set
{
_gradePointAverage = value;
OnPropertyChanged("GradePointAverage");
}
}
}
These properties serve as the source properties. When changed,
both these properties fire
PropertyChanged
event
that carries the corresponding property name in its event argument. This allows
the binding to update its target properties to the new values. StudentData
plays the role of a ViewModel
in this
simple example.
The View is located within the MainWindow.xaml file. It simply displays the student data
within a Grid panel. The important parts are the WPF bindings connecting the
ViewModel's
StudentData
properties to properties of the TextBoxes
within the View:<TextBox Text="{Binding Path=StudentFirstName}"
Grid.Row="1"
Grid.Column="2"
VerticalAlignment="Center" />
...
<TextBox Text="{Binding Path=StudentGradePointAverage}"
Grid.Row="2"
Grid.Column="2"
VerticalAlignment="Center" />
The TextBoxes'
Text
properties serve as the binding's targets.
Looking at the XAML code above, one might wonder how the Text
property knows which
StudentData
object it should connect to. There are
different ways to specify the source object within the binding, e.g., by
settingSource
, ElementName
or RelativeSource
properties of the binding. However, when
those properties are not set, as in our sample, the Binding's source object is
assumed to be specified by the DataContext
property of the corresponding visual
element. DataContext
property has a feature that it propagates
down the Visual Tree from ancestor to its descendants, unless changed
explicitly or unless it hits a ContentControl
or anItemsControl
on its path (to be explained later). So
once the DataContext
is set to the root element of the Visual
Tree, e.g. the Window, most elements under that tree will have the same DataContext
. MVVM pattern uses this frequently
by setting the View's DataContext
property to contain the ViewModel for that
View.
In our case, the
DataContext
is set within MainWindow
class constructor inside MainWindow.cs file:this.DataContext = _studentData;
Correspondingly, the two
TextBox
elements within MainWindow.xaml file will have the same DataContext
as their MainWindow
ancestor and the bindings will connect the StudentFirstName
andStudentGradePointAverage
properties from _studentData
object to the corresponding TextBox
'es properties.
When source property and target property depend on each other, but
are not equal (they can even be of different types) WPF Binding can employ the
ValueConverters
which transform the source property value
into the target property value and vice versa.
DataTemplates
The above binding sample shows how to bind properties on a
ViewModel
to the
corresponding properties within the View. However if we want to present
multiple data objects of the same structure, it is better to factor out the
presentation code as a DataTemplate
.SimpleDataTemplateTest
solution contains a DataTemplate
sample. The ViewModel is exactly the same
as in the previous sample - represented by StudentData
and it is attached to the View's DataContext
within MainWindow
class'es constructor. The View itself,
however, is defined by the DataTemplate
"StudentView
"
defined within the resources of MainWindow
inside MainWindow.xaml file:<DataTemplate x:Key="StudentView"
DataType="this:StudentData">
...
</DataTemplate>
To display the
StudentData
object using the DataTemplate
, a ContentControl
element is employed:<ContentControl Content="{Binding}"
ContentTemplate="{StaticResource StudentView}" />
Its
Content
property is bound directly to its DataContext
(since the binding path is not specified),
making itsContent
to be set to the StudentData
object. It's ContentTemplate
property is set to the "StudentView
"
data template. The ContentControl
"marries" the data and the DataTemplate
producing the visual representation of the
data.
Note that the Visual children/descendents of a
ContentControl
will have the ContentControl
's Content
property as their DataContext
. Also note that DataContext
does not automatically propagate to theContent
property of the ContentControl
. In order for the Content
to be
set to the ContentControl'sDataContext
, it
has to be explicitly bound to it.ContentTemplate
is ideal to display a signed data item in a
View, but if one has a collection of data,ItemsControl
class can be employed instead to display
the whole collection. For ItemsControl
sample, see ItemsControlDataTemplateTest.sln solution:
In this solution, the ViewModel is represented by
StudentListViewModel
class which contains a collection ofStudentData
objects within its TheStudents
property. ItemsControl
element is used to display the collection
of students:<ItemsControl ItemsSource="{Binding TheStudents}"
ItemTemplate="{StaticResource StudentView}" />
ItemsControl's
ItemsSource
property
is bound to the collection of students and ItemTemplate
property provides the DataTemplate
for each element within that collection.
Note that the
ItemsControl
's
children cells will have the corresponding element from the ItemsSource
collection as their DataContext
.
Using Commands for Passing the Events from the View to the
ViewModel
Now, suppose that we have a button as part of the View. We want
some action to be taken by the ViewModel when the button is pressed. This can
be achieved by employing the WPF Commands or Microsoft Expression SDK
interactivity functionality. I prefer the 2nd method, but using the commands is more
wide-spread so, we'll discuss it here first.
Command objects are derived from
ICommand
interface which has two important methods: CanExecute
method controls whether the
corresponding control (e.g. Button
or MenuItem
) that
is bound to this command is enabled or disabled, and Execute
method
specifies the action to be taken once the Button
or MenuItem
is
clicked. Here, we are using the DelegateCommand
which simply allows us to set arbitrary
delegates for these two methods. These delegates are passed within the
constructor of the DelegateCommand
.
Command sample is located under CommandSample.sln solution. After starting the solution,
press the button in the middle and you'll see the message with the popup:
CommandSampleViewModel
represents the ViewModel for the sample. It
contains a DelegateCommand
as itsTheCommand
property. Its "CanExecute
"
delegate always returns "true
" thus keeping the corresponding
button always enabled. Its "Execute
" delegate is implemented by the
"OnExecute
"
function which simply shows a Message Box with "Command Executed"
text. Please note, that in real life coding, you should not put any visual code
within the ViewModels, even the calls to MessageBox.Show
. Here
I did it just for brevity and clarity sake so that the OnExecute
function
would perform something that the users can see.
The
Button
within the view file MainWindow.xaml binds its Command
property to the TheCommand
property of the view model...<Button Content="Call Command"
Width="100"
Height="25"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Command="{Binding TheCommand}"/>
...which ensures that the command fires on the button click.
Using Microsoft Expression Blend SDK Interactivity Functionality
for Passing the Events from the View to the ViewModel
The WPF commands have a shortcoming that they can only be attached
to a few visual controls that have
Command
property,
e.g. Button
or MenuItem
and they only fire on Click events.
Microsoft Expression Blend SDK Interactivity functionality is much more generic
in a sense that it allows to trigger corresponding methods on the ViewModel for
almost any event that occurred on almost any visual element within the View.
Microsoft Expression SDK sample can be found in MSExpressionSDKInteractivitySample.sln solution. To make the Microsoft Expression
Blend SDK interactivity functionality available to the project, we need to add
two DLL files to the project's references: Microsoft.Expression.Interactions.dll and System.Windows.Interactivity.dll files. These files are part of Microsoft
Expression Blend SDK but can be used separately from the rest of the SDK. They
are located under MSExpressionBlendSDKDlls directory.
The sample shows how to trigger a ViewModel's method when the
MouseEnter
event is fired on a Rectangle
object. After starting the sample,
move the mouse pointer over the blue rectangle in the middle, and you'll see aMessageBox
popping up.
The ViewModel is represented by
MSExpressionBlendSDKSampleViewModel
class. It has just one methodMethodToCallOnMouseEnterEvent
which pops up a message box (remember that
you should not put any visual code including the MessageBox
related code into the real life ViewModels.
I put it here simply for the sake of clarity). The View is calling this method
via Microsoft Expression Blend SDK's EventTrigger
andCallMethodAction
:<Rectangle x:Name="TheRectangle"
Fill="Blue"
Width="100"
Height="100"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter"
SourceObject="{Binding ElementName=TheRectangle}">
<se:CallMethodAction MethodName="MethodToCallOnMouseEnterEvent"
TargetObject="{Binding Path=DataContext, ElementName=TheRectangle}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
Unlike the commands, Microsoft Expression Blend SDK functionality
does not provide a way to disable a visual element on which they
"listen" for events. It makes perfect sense, because they can be used
with the visual elements that cannot be disabled, e.g., Rectangle in the sample
above. If you want to provide an ability to control whether an element is
enabled or not via the ViewModel, you can simply bind that element's
IsEnabled
property to some boolean
property within the ViewModel.
MVVM Sample
While the samples above showed how to use different WPF components
to connect the View and the ViewModel, this example puts everything together
and shows the MVVM pattern in action.
The MVVM sample can be found under MVVMSample.sln solution. It allows to get a list of
students from a mock server, to add or remove entries corresponding to the
individual students, to modify individual student's properties and to save the
list to the mock server:
The ViewModel for the whole application is represented by
StudentListViewModel
class. This class contains a collection of
ViewModel objects of type StudentViewModel
class. StudentViewModel
class defines the ViewModel for the
individual students.
When the sample is started "Save Students" and "Add
New Student" buttons are disabled to force the user to load the student
data from the mock server. Once the student data is loaded, those buttons get
enabled. These button's enabled/disabled state is controlled by
IsSaveStudentsActionEnabled
andIsAddStudentsActionEnabled
properties of StudentListViewModel
class. The actions that need to be
performed once any of these buttons are clicked are defined by the ViewModel's
methodsGetStudentsAction
, SaveStudentsAction
and AddStudentAction
and are mapped to the button's click events
using Microsoft Expression Blend Interactivity functionality.
ViewModel representing the individual students is defined by
objects of
StudentViewModel
class, which has three properties FirstName
, LastName
and GradePointAverage
. It also defines a
methodDeleteStudentAction
used to delete the object from its parent
collection. This method callsDeleteStudentEvent
event which triggers the removal.
The corresponding Views are defined as the
DataTemplates
within StudentsViewResources.xaml resource dictionary located under XAMLResources folder. StudentView
is the DataTemplate
for a single student defined by StudentViewModel
object and StudentListView
is the DataTemplate
for the whole application.
The
MainWindow
class contains only a ContentControl
that converts the StudentListViewModel
object to display as StudentListView.
MVVM Discussions
Different MVVM Flavors
All the MVVM samples presented above have their Views represented
by the
DataTemplates
. I
thinkDataTemplates
are the best for representing the views
because their usage provides the clearest separation between the visual and
non-visual functionality. In some projects, however, people prefer to useUserControls
as views. In my experience, UserControls
or CustomControls
should be avoided as much as possible
within the MVVM pattern, since they are more heavy weight than the templates
and have some code behind, which can easily degenerate into containing some
business logic.
When to Use UserControls
There are, however, two important cases when building a
UserControl
or a CustomControl
is required:- When
you are building a brand new control with brand new capabilities. For
example, WPF does not contain built-in charting functionality, so, when
you build a charting control, you are forced to build a
UserControl
or aCustomControl
that takes some data input and draws a chart based on it. - When
you are forced to use the functionality of an existing control and that
existing control does not have the required capabilities, or does not
provide ways to bind to all the data, you will have to extend such control
to provide the required capabilities and to fit it in as MVVM View's
building block. Example of such a control would be a DevExpress
GridControl
which has great features and great performance but was not built with MVVM in mind and therefore requires a lot of adaptations.
In summary - do not use
UserControls
or CustomControls
to put together the Views within MVVM
patter - this is better achieved by the DataTemplates
(in conjunction with the DataTemplateSelectors
,ControlTemplates
, Styles
and StyleSelectors
). Use User and Custom controls
to create building blocks for the Views within MVVM pattern instead, when
necessary.
Multiple Views and ViewModels within an Application
Based on the discussion above, here is the diagram of
communications between different modules within a well-built MVVM application
Each one of the Views interacts only with its personal ViewModel.
The ViewModels, however, interact with the rest of the functionality: other
ViewModels, Models, Services, etc. Please note that the ViewModels still need
to be as independent of each other as they can be, to adhere to the separation
of concerns principle. The fact that some ViewModels need to communicate
between each other does not imply that they have to know each other's exact
types. They can communicate e.g. via common interfaces or an event aggregator
(for an example of an event aggregator, see e.g. Prism for Silverlight/MEF in Easy Samples. Part 3 - Communication
between the Modules).
Which View Properties should be Controlled by the ViewModel
Potentially the ViewModel can contain any types of non-visual
object including the objects used only within the Views, e.g.
Brushes
or text
label string, etc. For example, we could add BackgroundBrush
property to theStudentViewModel
class described above and bind our View's Background
property to it. On the other hand, there is
no reason for StudentViewModel
to contain information about the background
colors. The background brush can be specified very well by the View. Putting it
into the ViewModel will only confuse potential users of the class. The rule of
thumb is that the ViewModel should only contain the data displayed within the
view and methods and properties that can be used for interacting with other
ViewModels. Different brushes, colors, animations, changes of colors and shapes
that do not affect any other Views can very well be handled by the View itself
with the help of the WPF provided tools like Triggers StyleSelectors
andDataTemplateSelectors
.
Advantages of the MVVM Pattern
The major advantage of the MVVM pattern is that it provides the
best separation
of concerns: under MVVM, View is in charge of the visual representation while
the non-visual ViewModel is in charge of all of the interactions with the rest
of the software including the Model, the Services (usually via the Model) and
the rest of the ViewModels. All the MVVM advantages derive from this feature:
- Flexibility
and Customization - Different
Views can be used with the same ViewModels allowing completely different
visual representations of the same functionality depending on what
different customers want.
- Re-use - Because of the separation of Visual
and non-Visual functionality, both the Views and the ViewModels have
higher potential for re-use than if the Visual and non-Visual
functionality were mixed, since e.g. a non-visual functionality usually
would not be able to make use of a functionality that contains a Visual
part to it.
- Separation
of the UI design and development - MVVM makes it possible to separate
the work of the developer and the designer as clearly as possible: at
first the developer can produce an application with the crudest possible
GUI. Then the designer, using designer tools will be able to modify the
GUI (the Views) without touching any non-visual code.
- Testing - Writing automated tests for a Visual
application is not easy. The View - ViewModel separation allows the
ViewModel to be unit tested without the view. Since the ViewModel is in
charge of the interactions with the rest of the application, such unit
tests would cover the most important functionality while the View tests
will only have to contain testing of the visual features, e.g. colors,
animations, etc.
Some MVVM Pattern History
Model-View-ViewModel (MVVM) pattern evolved together with WPF as a
new way of designing and building Visual applications.
It came naturally out of new programming concepts developed as
part of WPF such as Bindings and DataTemplates. MVVM pattern was first
introduced by Martin Fowler in Presentation
Model and
John Gossman inModel-View-ViewModel (MVVM) pattern. Since
then, a lot of other people wrote about this pattern - the most famous article
is probably by Josh Smith in WPF
Apps With The Model-View-ViewModel Design Pattern.
·