introduction to wpf with mvvm
Post on 07-Aug-2018
261 Views
Preview:
TRANSCRIPT
-
8/20/2019 Introduction to WPF With MVVM
1/26
Paul Grenyer © May 2011
An Introduction to the Windows Presentation Foundation with theModel-View-ViewModel
Part 1
Paul Grenyer
After three wonderful years working with Java I am bak in the !" arena and ama#ed byhow things have hanged$ %hen I was working with !" &reviously it was with $'et 1$1 andas I return $'et ( is ready to go$ I started a new ontrat and my lient suggested that toget ahead of the game I should learn %indows Presentation )oundation *%P)+, the latestMirosoft framework for reating %indows deskto& *and web+ a&&liations$ It re&laes thelikes of %indows )orms on the deskto&$ -wo of the ma.or features of %P) are that it isrendered entirely on a om&uter/s gra&his ard and se&arates &resentation from&resentation logi$
Manning is my &referred tehnial book &ublisher, so I bought the P) version of %P) In Ation with isual tudio 2003 4%P)InAtion5 and read it on my 6indle$ It is a greatintrodution to &roduing Gra&hial 7ser Interfaes *G7Is+ with %P), but I later disoveredthat although Model8iew8iewModel *MM+ is overed, the detail is not great$ -heMM &attern is similar to Martin )owler/s Presentation Model 4Presentation model5, butwhere the &resentation model is a means of reating a 7I &latform8inde&endentabstration of a view, MM is a standardised way to leverage ore features of %P) tosim&lify the reation of user interfaes$ )ortunately there is a great M' Maga#ine artilealled %P) A&&s %ith -he Model8iew8iewModel esign Pattern 4MM5 that e9&lains itsim&ly and in a fair amount of detail$
CanonCanon - Any comprehensive list of books within a field.
8 ditionary$om
-o demonstrate %P) with MM I am going to inrementally develo& a small a&&liationwhih allows the user to searh an arhive of books$ -he a&&liation is alled !anon andthe soure ode 4oure!ode5 is available for download from my website$ I develo&ed!anon using isual tudio 2010 and $'et (, but %P) a&&liations an also be reatedwith isual tudio 2003 and $'et :$;$ I have assumed that the reader is following along$
)ire u& isual tudio and reate a new %P) A&&liation alled !anon$
-
8/20/2019 Introduction to WPF With MVVM
2/26
Paul Grenyer © May 2011
Figure 1: Default WPF Application Window
As with any normal window you should be able to minimise, ma9imise, resi#e and lose it$
If you take a look at the &ro.et struture in isual studio you/ll see there a&&ear to be .usttwo soure files, App.xaml and MainWindow.xaml$ Atually there are four soure files$ If
you use the arrow ne9t to eah file to e9&and it you will see that eah $xaml file has a
orres&onding $cs file= App.xaml.cs and MainWindow.xaml.cs$ I/ll e9&lain the
relationshi& between all four files shortly, but first I want to &ut all views into a View folder
and the view names&ae$ In isual tudio, reate a &ro.et level folder alled View and
move MainWindow.xaml into it$ MainWindow.xaml.cs will ome along with it$ -hen go
into MainWindow.xaml.cs and hange the names&ae from Canon to Canon.View$
-hen go into MainWindow.xaml and modify the x:Class attribute of the Window
element so that it reads=
-
8/20/2019 Introduction to WPF With MVVM
3/26
Paul Grenyer © May 2011
idebar= Adding %P) A&&liations to oure !ontrol
As with most isual tudio solutions you need to ensure you hek in all soure files,and not binaries or other build artefats$ oure file inlude the .xaml and .xaml.cs
files$
WPF Project Structure
%P) uses >AM? *&ronouned zammel +, whih stands for eXtensible A&&liation Marku&Language, to layout 7ser Interfaes *7Is+$ As we/ve seen all .xaml files have a
orres&onding xml.cs soure file file$ In most ases anything that an be defined in
>AM? an also be written in !" and vie8versa$ AM? and others in !"$
?et/s start by taking a look at %P)/s e@uivalent to main, App.xml and App.xml.cs,
starting with App.xml:
AM?$ %e/ll wantto hange this shortly when we in.et a view model$
'ow that we understand how a %P) a&&liation is defined let/s take a look at how awindow is defined by e9amining MainWindow.xaml and MainWindow.xaml.cs$
:
-
8/20/2019 Introduction to WPF With MVVM
4/26
Paul Grenyer © May 2011
MainWindow.xaml is in the View folder we reated earlier$ Its name and loation
orres&ond to the value of the StartupUri attribute in the Application element in
App.xaml$ -herefore it is the first window that will be dis&layed$
-
8/20/2019 Introduction to WPF With MVVM
5/26
Paul Grenyer © May 2011
p',lic partial class %pp+ p',lic %pp + new MainWindow.&how3 --
If you run the a&&liation again now *you need to add=
'sin! Canon.)iew3
of ourse+, you will see e9atly the same window$ All we/ve done is move the reation ofthe first window from >AM? to !"$ 'ow we have an instane of a window to in.et a viewmodel into$
A view model need be nothing more om&le9 than a normal lass$ It does not re@uire anys&eial base lass, interfaes or members$ It/s .ust about the data$ !reate a &ro.et levelfolder alled ViewModel and reate the following lass in it *don/t forget to add it soure
ontrol+=
namespace Canon.)iewModel+ p',lic class MainWindow)iewModel + --
very %P) view has a $ataContext &ro&erty of ty&e o%&ect$ -his &ro&erty is null
unless a view model is in.eted into the view$ %hen a view model is in.eted %P) seesthat $ataContext is no longer null and uses it$ %e/ll over an e9am&le of sim&le binding
shortly$ -he $ataContext &ro&erty is also available within the view$ -his means the view
knows about the view model it has, but the view model ontinues to know nothing aboutthe view that/s using it$ Bou an In.et the view model into the view by reating an instaneof it and setting the $ataContext &ro&erty on the view=
p',lic partial class %pp+ p',lic %pp + new MainWindow
+ 4ataContext = new MainWindow)iewModel -.&how3 --
If you run the a&&liation again there will be no differene$ omething in the view must bebound to a &ro&erty in the model to see a differene in the 7I$
A Slight Case of Over Binding
-
8/20/2019 Introduction to WPF With MVVM
6/26
Paul Grenyer © May 2011
detail in %P) in Ation1$
I think the best way to demonstrate binding is with a sim&le e9am&le$ In this one we/ll bindthe main window/s title to a &ro&erty in the view model$ ?et/s start off by adding the&ro&erty to the view model=
p',lic class MainWindow)iewModel+ p',lic strin! %ppTitle + !et + ret'rn "Canon"3 - --
Cne the binding is in &lae the main window will dis&lay the string returned by theAppTitle &ro&erty$ -o bind the window title to the &ro&erty we have to modify the Title
attribute of the Window element in MainWindow.xml from=
-
8/20/2019 Introduction to WPF With MVVM
7/26
Paul Grenyer © May 2011
8',lisher = strin!.mpt;3 1&59 = strin!.mpt;3 -
p',lic oerride ,ool 'also,>ect o,> + if *eference'alsn'll? o,> ret'rn false3 if o,>.etT;pe @= t;peof5oo ret'rn false3
ret'rn 'als5ooo,>3 -
p',lic ,ool 'als5oo other + if *eference'alsn'll? other ret'rn false3 ret'rn 'als1d? other.1d3 -
p',lic oerride int etashCode + ret'rn 1d.etashCode3 -
--
-his sim&le 'oo( lass ontains a uni@ue nullable id for eah book, its title, author,
&ublisher and I
-
8/20/2019 Introduction to WPF With MVVM
8/26
Paul Grenyer © May 2011
p',lic class &imple5oo*epositor; : 15oo*epositor;+ priate readonl; 1Aist
-
8/20/2019 Introduction to WPF With MVVM
9/26
Paul Grenyer © May 2011
-
idebar= Simple'oo(Repositor)
-he Simple'oo(Repositor) mok ob.et is fairly straight forward$ It &ersists a list of
books in the %oo(s list=
'ote that if the Searc*ields method returns true the Searc method knows it/s
found a mathing book, sto&s iterating through the books and returns the urrent book$ Cfourse there might be multi&le mathes, but the Searc method only returns the first
math$
-he Save method an both u&date e9isting books and save new ones$ 'ew books are
identified as having a null Id$ If the book being saved has an id and is already in the
book list, it is removed$ -his may seem a little odd$ owever, if the e9isting book is .ustadded to book list it will be in there twie$ Also remember that books are om&ared for
e@uality by their ids$ AM?=
Figure : !anon "ser Interface M# I
-
8/20/2019 Introduction to WPF With MVVM
10/26
Paul Grenyer © May 2011
-he first thing you might notie is that the !anon 7I is smaller than the default window&itured in figure 1$ -his is beause I modified the Window element in MainWindow.xaml
to s&eify a starting height and width and a minimum height and width=
-
8/20/2019 Introduction to WPF With MVVM
11/26
Paul Grenyer © May 2011
-ool bars usually sit within a Tool'arTra) whih hel&s give them the usual %indows look
and feel and an host multi&le tool bars$ -o insert the Tool'arTra) into the $oc(+anel
you .ust make it a hild element$ Bou/ll notie that the Tool'arTra) inherits the
$oc(+anel.$oc( attribute from its &arent and uses it to s&eify that the Tool'arTra)
should be dis&layed at the to&$ !hild ontrols inheriting &ro&erties from their &arents is aommon ourrene throughout %P) and makes for far less verbose >AM?$ %P) In
Ation disusses this in more detail2$ -he Tool'ar is a hild of the Tool'arTra)$
If you run the a&&liation again now you will see that the toolbar takes over the wholelient area of the window$ %e only want it to be a thin stri& aross the to& and we want therest of the area to be a !rid layout$ All we have to do is add a !rid to the $oc(+anel=
-
8/20/2019 Introduction to WPF With MVVM
12/26
Paul Grenyer © May 2011
maintains it$ -he button/s "s$e-ault attribute is also set to true as we want the searh
button to be the default ation$ -he te9t bo9/s label is s&eified between the o&en andlosing elements$ -his is also @uite ommon for %P) ontrols$ If you run the a&&liationyou an enter te9t into the te9t bo9 and lik the button$ -he button does not do anythingyet as it does not have a ommand assoiated, I/ll disuss ommands in the ne9t setion$
o far we/ve looked at the $oc(+anel and Stac(+anel layouts$ -hese are two of themost im&ortant %P) layouts, but by far the most useful and therefore the most ommonlyused layout is the !rid layout$ It has rows and olumns like any other grid and allows you
to to &ut any ontrol in any sell or aross many ells$ In most ases rows and olumns aredefined using Row$e-inition and Column$e-inition elements=
-
8/20/2019 Introduction to WPF With MVVM
13/26
Paul Grenyer © May 2011
-
8/20/2019 Introduction to WPF With MVVM
14/26
Paul Grenyer © May 2011
: thisexec'te? n'll +-
p',lic *ela;Command%ctionect$ exec'te? 8redicateect$ canxec'te + if exec'te == n'll + throw new %r!'ment9'llxception"exec'te"3
-
this.exec'te = exec'te3 this.canxec'te = canxec'te3 -
4e,'!!er&tepThro'!hN p',lic ,ool Canxec'teo,>ect parameter + ret'rn canxec'te == n'll 7 tr'e : canxec'teparameter3 -
p',lic eent entandler Canxec'teChan!ed
+ add + CommandMana!er.*e'er;&'!!ested G= al'e3 - remoe + CommandMana!er.*e'er;&'!!ested E= al'e3 - -
p',lic oid xec'teo,>ect parameter + exec'teparameter3 --
howing how it is used should &rovide enough e9&lanation of it for our &ur&oses$ If youwant to understand it in more detail see %P) A&&s %ith -he Model8iew8iewModel
esign Pattern$ ome &eo&le reommend la#y loading Rela)Command ob.ets=
priate *ela;Command OsaeCommand3p',lic 1Command &aeCommand+ !et + if OsaeCommand == n'll + OsaeCommand = new *ela;Command...3 - ret'rn OsaeCommand3 -
-
but I really don/t see the need$ It/s a lot of e9tra ode, inluding a null hek and the
&ro&erty is aessed as soon as the window is dis&layed and bound anyway$ o I .ust dothis=
p',lic class MainWindow)iewModel+ ... p',lic strin! &earchText + !et3 set3 - p',lic 1Command *'n&earch+ !et3 priate set3 -
p',lic MainWindow)iewModel15oo*epositor; repo + ... *'n&earch = new *ela;Commando =$ &earch? o =$ can&earch 3
1(
-
8/20/2019 Introduction to WPF With MVVM
15/26
Paul Grenyer © May 2011
-
priate ,ool can&earch + ret'rn @strin!.1s9'llPrmpt;&earchText3 -
priate oid &earch
+
- ...-
-he getter of the RunSearc &ro&erty is &ubli so that it an be bound to, but the setter is
&rivate so that it an only be set internally$ -he Rela)Command ob.et itself is reated in
the view model onstrutor=
*'n&earch = new *ela;Command o =$ &earch? o =$ can&earch 3
-ake another look at the Rela)Command/s two &arameter onstrutor=
p',lic *ela;Command%ctionect$ exec'te? 8redicateect$ canxec'te
-he first &arameter is an Action delegate, whih ena&sulates a method that has a single
&arameter and does not return a value$ A lambda e9&ression is used to s&eify the methodto all when the ommand is e9euted$ As it/s a delegate you ould do all sorts of in8lineommand im&lementations, but I find it learer to delegate to another method$ -he seond&arameter is a +redicate delegate, whih re&resents a method that defines a set of
riteria and determines whether the s&eified ob.et meets those riteria$ A lambdae9&ression is used to s&eify a method that determines whether the ommand should beenabled$ *-he o &arameter is ignored as it is not needed in this senario+$ -o determine if
the ommand should be enabled, we look to see if SearcText is not null or is em&ty=
priate ,ool can&earch+ ret'rn @strin!.1s9'llPrmpt;&earchText3-
-he ne9t stage is to bind the ommand to the button$ -his is ahieved by by adding aCommand attribute to the searh 'utton element=
-
8/20/2019 Introduction to WPF With MVVM
16/26
Paul Grenyer © May 2011
disables de&ending on whether the te9t bo9 has ontent$ owever, when liked thebutton still does nothing$ In the ne9t setion we/ll look at finishing the binding and gettingbooks from the re&ository$
-
8/20/2019 Introduction to WPF With MVVM
17/26
Paul Grenyer © May 2011
...
-he -itle, Author, Publisher and I
-
8/20/2019 Introduction to WPF With MVVM
18/26
-
8/20/2019 Introduction to WPF With MVVM
19/26
Paul Grenyer © May 2011
4component &eifies that the assembly being referred to is referened from the
loal assembly$
0images0ligt%ul%.png -he relative &ath to the image file$
Menus and Tool Bar Icons As it stands the !anon a&&liation is not very useful as it only allows us to searh for thetwo &reloaded books$ %hat it needs to be able to do ne9t is save u&dates to those booksand reate new ones$ ave ations are often invoked by a menu andLor tool bar button orvia a keyboard shortut$ 'e9t I/ll show you how to add a menu, with menu items bound toommands, whih share an ion with a tool bar button we/ll add to a new tool bar$ )irst adda menu to the to& setion of the dok &anel=
-
8/20/2019 Introduction to WPF With MVVM
20/26
Paul Grenyer © May 2011
... *'n&ae = new *ela;Commando =$ &ae? o =$ can&ae3 -
priate ,ool can&ae + ret'rn tr'e3 -
priate oid &ae +--
-he canSave method .ust returns true for the time being$ %e/ll &ut it to better use later$
Menu items an also have images and the same image an be used for a tool bar buttontoo$ Bou ould re&eat the loation of the image for both the menu item and the tool barbutton, but a better solution is to add a resoure=
?ey$%Sa=e4mage% 6riSo3r,e$%/Canon;,omponent/images/disk.png% /
*/+o,k-anel.Reso3r,es
-
8/20/2019 Introduction to WPF With MVVM
21/26
Paul Grenyer © May 2011
*B3tton Command$%{Binding R3nSa=e}% *4mage So3r,e$%{Stati,Reso3r,e Sa=e4mage}% /
*/B3tton */ToolBar
-
8/20/2019 Introduction to WPF With MVVM
22/26
Paul Grenyer © May 2011
Pn8ropert;Chan!ed"Title"3 Pn8ropert;Chan!ed"%'thor"3 Pn8ropert;Chan!ed"8',lisher"3 Pn8ropert;Chan!ed"1&59"3 - -
... priate oid &ae + c'rrent5oo = repo.&aenew 5oo + 1d = c'rrent5oo.1d? Title = Title? %'thor = %'thor? 8',lisher = 8',lisher? 1&59 = 1&59 -3 -
-
-o hold the referene we add a book field alled current'oo( to the
MainWindowViewModel$ %e default initialise it in the onstrutor to make sure it is valid
even if a book has not been loaded yet$ -hen if we find a book when we searh for one weset the current'oo( referene to the new book$ )inally when we save the new book we
use the "d from current'oo( to reate a new book instane$ After a suessful save we
set current'oo( to the new book instane$ -ry it out and see if you an s&ot the further
flaw$
-he only way to reate a new book is to enter values into all the fields and save beforesearhing for a book and even then you an only do it one$ %hat we need is a new bookmenu item, image and tool bar button=
-
8/20/2019 Introduction to WPF With MVVM
23/26
Paul Grenyer © May 2011
-
8/20/2019 Introduction to WPF With MVVM
24/26
Paul Grenyer © May 2011
Bou an of ourse add images and a orres&onding tool bar in the way already desribed$ere we/ve re&laed the ommand bindings with the system ommands for ut, o&y and&aste$ If you run the a&&liation you/ll find ut, o&y and &aste .ust work as e9&eted$%P) In Ation 4%P)InAtion5, the book in Introdued in &art 1, goes into the systemommands in more detail($
'ot all system ommands are as straight forward$ 7nfortunately if you add the systemClose ommand to the file menu=
-
8/20/2019 Introduction to WPF With MVVM
25/26
Paul Grenyer © May 2011
"s$irt) is a boolean &ro&erty the indiates if any hanges have been made$ In the ase
of AppTitle it is used to determine whether an asterisk should be a&&ended to the title
when there are hanges and in the ase canSave it is .ust returned to indiate if the
ommand should be enabled$
p',lic ,ool 1s4irt;
+ !et + ret'rn @c'rrent5oo.Title.'alsTitle JJ @c'rrent5oo.%'thor.'als%'thor JJ @c'rrent5oo.8',lisher.'als8',lisher JJ @c'rrent5oo.1&59.'als1&593 --
-he "s$irt) &ro&erty om&ares the urrent book fields against the e@uivalent 7I fields to
determine if there are any hanges$ 7nfortunately this leads to some more verbosehanges to the 7I field &ro&erties to get the title and save ommand to u&date in real time=
priate strin! title = strin!.mpt;3p',lic strin! Title+ !et + ret'rn title3 - set + title = al'e3 Pn8ropert;Chan!ed"Title"3 PnChan!e3 --
$$$priate oid PnChan!e+ Pn8ropert;Chan!ed"%ppTitle"3-
I have only shown the hanges for the Title &ro&erty, but the Autor, +u%liser and
"S'3 &ro&erties must be hanged in the same way$ Instead of using the default &ro&erty
im&lementation we have to im&lement our own set method so that when the &ro&erty is
u&dated we an tell %P) to also u&date the window title$ -his means we also need toseparately store the &ro&erty value, whih is initialised to an em&ty string to math thedefault 'oo( instane, and im&lement a get method too$ Cne advantage is that we an
also move the %P) notifiation that the &ro&erty has hanged to the &ro&erty itself so thatwe don/t need to remember to all n+ropert)Canged anywhere else in the ode
where we assign the &ro&erty$ o the Update method is redued to=
priate oid (pdate5oo ,oo+ c'rrent5oo = ,oo3
Title = ,oo.Title3
%'thor = ,oo.%'thor3 8',lisher = ,oo.8',lisher3 1&59 = ,oo.1&593-
2;
-
8/20/2019 Introduction to WPF With MVVM
26/26
Paul Grenyer © May 2011
-he window title also needs to be u&dated when a book is saved as there are no longerany hanges=
priate oid &ae+ c'rrent5oo = repo.&aenew 5oo
+ 1d = c'rrent5oo.1d? Title = Title? %'thor = %'thor? 8',lisher = 8',lisher? 1&59 = 1&59 -3 nC#ange!;-
Finall#
-his is where this artile leaves the !anon a&&liation$ -here is more to do, but that falls
outside the so&e of an introdutory artile$ ere I introdued you to sim&le %P) 7Idevelo&ment and the Model8iew8iewModel &attern inluding sim&le binding andommands$ -hen I demonstrated how to make %P) G7Is more aesthetially &leasingwith the use of images and more user friendly with the use of menus and toolbars andshowed how to im&lement those menus and toolbars with ustom and system ommands$
In future artiles I will over unit testing and &atterns for maintaining the se&arationbetween the view model and the view when you want to dis&lay message bo9es and hildwindows or use ustom ontrols$
%eferences4%P)InAtion5 %P) In Ation with isual tudio 2003 by Arlen )eldman and Ma99aymon$ Manning$ I
top related