[ ii ]Implementing Dependency Injection 109 Connecting Views with View Models 118 Chapter 4: Becoming Proficient with Data Binding 127 Exploring the Binding class 132 Binding from within
Trang 2Mastering Windows
Presentation Foundation
.BTUFSUIFBSUPGCVJMEJOHNPEFSOEFTLUPQBQQMJDBUJPOTPO 8JOEPXT
Sheridan Yuen
BIRMINGHAM - MUMBAI
Trang 3Copyright © 2017 Packt Publishing
All rights reserved No part of this book may be reproduced, stored in a retrieval system, ortransmitted in any form or by any means, without the prior written permission of thepublisher, except in the case of brief quotations embedded in critical articles or reviews.Every effort has been made in the preparation of this book to ensure the accuracy of theinformation presented However, the information contained in this book is sold withoutwarranty, either express or implied Neither the author, nor Packt Publishing, and itsdealers and distributors will be held liable for any damages caused or alleged to be causeddirectly or indirectly by this book
Packt Publishing has endeavored to provide trademark information about all of the
companies and products mentioned in this book by the appropriate use of capitals
However, Packt Publishing cannot guarantee the accuracy of this information
First published: February 2017
Trang 5About the Author
Sheridan Yuen is a Microsoft NET MCTS and Oracle Java SCJP certified software
developer, living in London, England His passion for coding made him stand out from thecrowd right from the start From his second year onward at university, he was employed to
be a teaching assistant for the first year student coding workshops and has since returned as
a guest lecturer
Among other prestigious positions, he was the primary software developer for the Ministry
of Sound group for four years, working on their main music business application,
responsible for creating their multi award winning albums This application managed toincrease its users’ productivity by up to 80% in some cases
In addition to this, he architected a unique ticket scanning application for their awardwinning nightclub, making it the first club in the world to introduce scanned ticket entryacross all streams for their clients Coming from a musical background and being a
qualified audio engineer, with experience of record production and digital audio, this postwas a perfect union
He soon became a popular figure in the C# and WPF sections of the Stack Overflow,
“question and answer” website, being awarded enough reputation by the communitymembers to raise him to well within the top half percent of all users While authoring thisbook and other projects have kept him away for some time, he is keen to return to continue
to help new users to get to grips with WPF
I would like to thank my long suffering girlfriend Jemma, who has regularly had to make
do without my company for the best part of a year, for her patience while I was composing and writing this book and the many examples in it I’d also like to thank Chaitanya from
Packt Publishing for convincing me to write this book in the first place and without who, this book would not have been written.
Finally, I would like to thank Mary Thomson, Professor Sarah Barman and Professor
James Orwell in particular, from Kingston University, London, who inspired me to change the direction of my previous career and planted the seed of curiosity that has taken me so
far I would also like to thank James for encouraging me to move from the Bachelor’s
Trang 6About the Reviewer
Alex Golesh is an international expert in XAML-based technologies such as Universal
Windows Platform (Windows, Windows Phone, HoloLens, Xbox One), Xamarin.Forms,WPF, and Silverlight Also, Alex specializes in cloud-based solutions such as MicrosoftAzure Alex developed training solutions for Microsoft Learning on Windows Phone andWindows 8 and delivers workshops for developers and enterprises Alex leads the
architecture and development process in multiple projects for his clients
Trang 7For support files and downloads related to your book, please visit XXX1BDLU1VCDPN.Did you know that Packt offers eBook versions of every book published, with PDF andePub files available? You can upgrade to the eBook version at XXX1BDLU1VCDPN and as aprint book customer, you are entitled to a discount on the eBook copy Get in touch with us
at TFSWJDF!QBDLUQVCDPN for more details
At XXX1BDLU1VCDPN, you can also read a collection of free technical articles, sign up for arange of free newsletters and receive exclusive discounts and offers on Packt books andeBooks
I U U Q T X X X Q B D L U Q V C D P N N B Q U
Get the most in-demand software skills with Mapt Mapt gives you full access to all Packtbooks and video courses, as well as industry-leading tools to help you plan your personaldevelopment and advance your career
Why subscribe?
Fully searchable across every book published by Packt
Copy and paste, print, and bookmark content
On demand and accessible via a web browser
Trang 8Customer Feedback
Thanks for purchasing this Packt book At Packt, quality is at the heart of our editorialprocess To help us improve, please leave us an honest review on this book's Amazon page
at I U U Q T H P P H M Z V 6 " Q %
If you'd like to join our team of regular reviewers, you can email us at
DVTUPNFSSFWJFXT!QBDLUQVCDPN We award our regular reviewers with free eBooks andvideos in exchange for their valuable feedback Help us be relentless in improving ourproducts!
Trang 9Table of Contents
Chapter 1: A Smarter Way of Working with WPF 7
Introducing the ICommand interface 15
Handling events in Attached Properties 18
Chapter 2: Debugging WPF Applications 35
Outputting values to UI controls 48
Catching changing Dependency Property values 48
Chapter 3: Writing Custom Application Frameworks 52
Trang 10[ ii ]
Implementing Dependency Injection 109
Connecting Views with View Models 118
Chapter 4: Becoming Proficient with Data Binding 127
Exploring the Binding class 132
Binding from within control templates 141
Converting data bound values 143
Binding multiple sources to a single target property 149
Declaring read-only Dependency Properties 159
Registering Attached Properties 160
Prioritizing value setting sources 162
Displaying hierarchical data 175
Chapter 5: Using the Right Controls for the Job 183
Inheriting framework abilities 184
Trang 11Chapter 7: Creating Visually Appealing User Interfaces 309
Overriding default control styles 310
Declaring multiple borders 315
Exploring borderless windows 329
Trang 12[ iv ]
Chapter 8: Implementing Responsive Data Validation 367
Implementing the IDataErrorInfo interface 369
Introducing the INotifyDataErrorInfo interface 386
Chapter 9: Completing That Great User Experience 423
Discovering the Async and Await keywords 435
Building asynchrony into our framework 439
Producing in-application help 458
Extending common courtesies 463
Chapter 10: Improving Application Performance 470
Enhancing the performance of textual output 495
Trang 13Chapter 11: Deploying Your Masterpiece Application 514
Chapter 12: What Next? 537
Improving our application framework 540
Trang 14While it can be easy to construct a basic form using WPF, it takes a lot more to fully
understand what WPF can do for us and how best to use it It has a steep learning curve and
it can be difficult to comprehend this very different way of working This book aims to helpyou to get over that initial hill and continue to fully enable you to implement any givenrequirement
This book will start by providing you the foundation knowledge on how to improve yourworkflow and what to do when you have problems It will build upon this foundation byintroducing the base layer of the application that will serve all that comes after it We willthen take a detour to cover data binding in detail
The book will then turn to the User Interface (UI) and how to get the most out of the built-inand custom WPF controls It will make clear which customization methods are best toutilize in a wide range of scenarios, avoiding the need to rewrite existing functionality.Other tips and tricks will also be provided to enable you to create your own visually
What this book covers
$IBQUFS, A Smarter Way of Working with WPF, introduces the Model, View, View Model
(MVVM) software architectural pattern and the benefits of using it with WPF
$IBQUFS, Debugging WPF Applications, provides essential tips on various methods of
debugging WPF applications, ensuring the ability to iron out any problems that may occur
$IBQUFS, Writing Custom Application Frameworks, introduces the indispensable concept of
application frameworks, with early examples that will be built upon as the book progresses
By the end of the book, you will have a fully functioning Framework with which to buildyour applications upon
Trang 15$IBQUFS, Becoming Proficient with Data Binding, demystifies data binding and clearly
demonstrates how to use it in a practical application A plethora of examples will help you
to understand which binding syntax to use in any given situation and to be confident thattheir bindings will work as expected
$IBQUFS, Using The Right Controls for The Job, explains which controls to use in particular
situations and describes the various ways to modify them when required It clearly outlineshow to customize existing controls and how to create custom controls when required
$IBQUFS, Mastering Practical Animations, explains the ins and outs of WPF Animations,
detailing lesser known functionality It concludes with a number of ideas for practicalanimations and continues to build upon the custom application framework
$IBQUFS, Creating Visually Stunning User Interfaces, offers advice for getting the most out
of the WPF visuals, while remaining practical, and provides handy tips on making
applications stand out from the crowd
$IBQUFS, Implementing Responsive Data Validation, presents a number of methods of data
validation to suit every situation and continues to build upon the custom applicationframework It covers full, partial, instant, and delayed validation and a variety of differentways to display validation errors
$IBQUFS, Completing That Great User Experience, provides tips for creating applications
with a great user experience Concepts introduced here, such as asynchronous data accessand keeping the end users well informed, will substantially improve the existing customapplication framework
$IBQUFS, Improving Application Performance, lists a number of ways to increase the
performance of WPF applications from freezing resources to implementing virtualization.Readers that follow these tips and tricks can rest assured that their WPF applications willperform as optimally as they can
$IBQUFS, Deploying Your Masterpiece Application, covers the final requirement for all
professional applications—deployment It includes the older method of using the WindowsInstaller software, along with the more common and up-to-date method of using ClickOncefunctionality
$IBQUFS, What Next?, summarizes what you have learned from this book and suggests
what you can do with many of your various new skills It provides you with further ideas
on extending the application framework
Trang 16[ 3 ]
What you need for this book
As with all WPF development, you'll need to have the NET Framework and a version ofMicrosoft's Visual Studio integrated development environment software installed on yourcomputer
You'll be able to use versions as old as 2010, but in order to use the code in the book thattakes advantage of the latest NET Framework improvements, you'll need to use one of thenewer versions Note that any edition of Visual Studio can be used, from the top of the lineEnterprise edition to the free Community (2015) edition
Who this book is for
This book is for working developers with a basic to moderate level of knowledge aboutWindows Presentation Foundation and for those interested in improving their practical day
to day WPF skills It will also be of special interest to individuals wanting to know moreabout application architecture and those wanting to improve the look of their user
interfaces
Conventions
In this book, you will find a number of text styles that distinguish between different kinds
of information Here are some examples of these styles and an explanation of their meaning.Code words in text, database table names, folder names, filenames, file extensions,
pathnames, dummy URLs, user input, and Twitter handles are shown as follows: "There aretwo other useful properties declared by the (SJE class."
A block of code is set as follows:
Trang 17Any command-line input or output is written as follows:
System.Windows.Data Error: 17 : Cannot get 'Item[]' value (type
'ValidationError') from '(Validation.Errors)' (type
'ReadOnlyObservableCollection`1').
BindingExpression:Path=(Validation.Errors)[0].ErrorContent;
DataItem='TextBox' (Name=''); target element is 'TextBox' (Name='');
target property is 'ToolTip' (type 'Object')
ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException:
Specified argument was out of the range of valid values.
New terms and important words are shown in bold Words that you see on the screen, for example, in menus or dialog boxes, appear in the text like this: "The Cancel button has been
declared in the second row and column."
Warnings or important notes appear in a box like this
Tips and tricks appear like this
Reader feedback
Feedback from our readers is always welcome Let us know what you think about thisbook-what you liked or disliked Reader feedback is important for us as it helps us developtitles that you will really get the most out of To send us general feedback, simply e-
mail GFFECBDL!QBDLUQVCDPN, and mention the book's title in the subject of your
message If there is a topic that you have expertise in and you are interested in either
writing or contributing to a book, see our author guide at XXXQBDLUQVCDPNBVUIPST
Customer support
Now that you are the proud owner of a Packt book, we have a number of things to help you
to get the most from your purchase
Trang 18[ 5 ]
Downloading the example code
You can download the example code files for this book from your account at I U U Q X X X Q
B D L U Q V C D P N If you purchased this book elsewhere, you can visit I U U Q X X X Q B D L U Q V C D
P N T V Q Q P S U and register to have the files e-mailed directly to you
You can download the code files by following these steps:
Log in or register to our website using your e-mail address and password
WinRAR / 7-Zip for Windows
Zipeg / iZip / UnRarX for Mac
7-Zip / PeaZip for Linux
The code bundle for the book is also hosted on GitHub at I U U Q T H J U I V C D P N 1 B D L U 1 V C M
J T I J O H B T U F S J O H 8 J O E P X T 1 S F T F O U B U J P O ' P V O E B U J P O We also have other code bundlesfrom our rich catalog of books and videos available at I U U Q T H J U I V C D P N 1 B D L U 1 V C M J T I
J O H Check them out!
Downloading the color images of this book
We also provide you with a PDF file that has color images of the screenshots/diagrams used
in this book The color images will help you better understand the changes in the output.You can download this file from I U U Q T X X X Q B D L U Q V C D P N T J U F T E F G B V M U G J M F T E P X O
M P B E T B T U F S J O H 8 J O E P X T 1 S F T F O U B U J P O ' P V O E B U J P O @ $ P M P S * N B H F T Q E G
Trang 19your book, clicking on the Errata Submission Form link, and entering the details of your
errata Once your errata are verified, your submission will be accepted and the errata will
be uploaded to our website or added to any list of existing errata under the Errata section ofthat title
To view the previously submitted errata, go to I U U Q T X X X Q B D L U Q V C D P N C P P L T D P O U F O
U T V Q Q P S U and enter the name of the book in the search field The required information will
appear under the Errata section.
Piracy
Piracy of copyrighted material on the Internet is an ongoing problem across all media AtPackt, we take the protection of our copyright and licenses very seriously If you comeacross any illegal copies of our works in any form on the Internet, please provide us withthe location address or website name immediately so that we can pursue a remedy
Please contact us at DPQZSJHIU!QBDLUQVCDPN with a link to the suspected pirated
material
We appreciate your help in protecting our authors and our ability to bring you valuablecontent
Questions
If you have a problem with any aspect of this book, you can contact us
at RVFTUJPOT!QBDLUQVCDPN, and we will do our best to address the problem
Trang 20previous GUI technology, Windows Forms However, as time passed, it has fallen far short
working that is required to master WPF
The last reason is that it is not a very efficient language and if a WPF application has lots of'bells and whistles' in, then either the client computers will need to have additional RAMand/or graphics cards installed, or they could face a slow and stuttering user experience.This explains why many companies that make use of WPF today are in the finance industry,where they can afford to upgrade all users' computers to be able to run their applicationsoptimally This book will aim to make WPF more accessible to the rest of us by providingpractical tips and tricks to help build our real-world applications more easily and moreefficiently
Trang 21One of the simplest changes with the biggest workflow improvements that we can make toimprove the way we work with WPF is to follow the MVVM software architectural pattern.
It describes how we can organize our classes to make our applications more maintainable,testable, and generally simpler to understand In this chapter, we will take a closer look atthis pattern and discover how it can help us to improve our applications
After discovering what MVVM is and what its benefits are, we'll learn several new ways tocommunicate between the various components in this new environment We'll then focus
on the physical structure of the code base in a typical MVVM application and investigate avariety of alternative arrangements
What is MVVM and how does it help?
Model-View-View Model (MVVM) is a software architectural pattern that was famously
introduced by John Gossman on his blog back in 2005 and is now commonly used when
developing WPF applications Its main purpose is to provide a Separation of Concerns
between the business model, the User Interface (UI), and the business logic It does this by
dividing them into three distinct types of core components: Models, Views, and ViewModels Let's take a look at how they are arranged and what each of these componentsrepresent
As we can see here, the View Models component sits between the Models and the Views
and provides two-way access to each of them It should be noted at this point that there
should be no direct relationship between the Views and Models components and only
loose connections between the other components Let's now take a closer look at what each
of these components represent
Trang 22A Smarter Way of Working with WPF
[ 9 ]
Models
Unlike the other MVVM components, the Model constituent comprises of a number ofelements It encompasses the business data model along with its related validation logic and
also the Data Access Layer (DAL), or data repositories, that provide the application with
data access and persistence
The data model represents the classes that hold the data in the application They typicallymirror the columns in the database more or less, although it is common that they are
hierarchical in form, and so may require joins to be performed in the data source in order tofully populate them One alternative would be to design the data model classes to fit therequirements in the UI, but either way, the business logic or validation rules will typicallyreside in the same project as the data model
The code that is used to interface with whatever data persistence technology is used in ourapplication is also included within the Models component of the pattern Care should betaken when it comes to organizing this component in the code base, as there are a number
of issues to take into consideration We'll investigate this further in a while, but for now,let's continue to find out more about the components in this pattern
as being a variation of the MVC pattern
They have two-way connections with the Model component in order to access and updatethe data that the Views require, and often, they transform that data in some way to make iteasier to display and interact with in the UI They also have two-way connections with theViews through data binding and property change notification In short, View Models formthe bridge between the Model and the View, which otherwise have no connection to eachother
However, it should be noted that the View Models are only loosely connected to the Viewsand Model components through their data binding and interfaces The beauty of this
pattern enables each element to be able to function independently from each other
Trang 23To maintain the separation between the View Models and the View, we avoid declaring anyproperties of UI-related types in the View Model We don't want any references to UI-related DLLs in our View Models project, and so we make use of custom
*7BMVF$POWFSUFS implementations to convert them to primitive types For example, wemight convert 7JTJCJMJUZ objects from the UI to plain CPPM values or convert the selection
of some colored #SVTI objects to an &OVN instance that is safe to use in the View Model
Views
The Views define the appearance and layout of the UI They typically connect with a ViewModel through the use of their %BUB$POUFYU property and display the data that it supplies.They expose the functionality provided by the View Model by connecting its commands tothe UI controls that the users interact with
In general, the basic rule of thumb is that each View has one associated View Model Thisdoes not mean that a View cannot data bind to more than one data source or that we cannotreuse View Models It simply means that, in general, if we have a class called
4FDVSJUZ7JFX, it is more than likely that we'll also have an instance of a class named4FDVSJUZ7JFX.PEFM that will be set as the value of that View's %BUB$POUFYU property
Data binding
One often overlooked aspect of the MVVM pattern is its requirement for data binding Wecould not have the full Separation of Concerns without it, as there would be no easy way ofcommunicating between the Views and View Models The XAML markup, data bindingclasses, and *$PNNBOE and */PUJGZ1SPQFSUZ$IBOHFE interfaces are the main tools inWPF that provide this functionality
The *$PNNBOE interface is how commanding is implemented in the NET Framework Itprovides behavior that implements and even extends the ever useful Command pattern, inwhich an object encapsulates everything needed to perform an action Most of the UIcontrols in WPF have $PNNBOE properties that we can use to connect them to the
functionality that the commands provide
Trang 24A Smarter Way of Working with WPF
[ 11 ]
The */PUJGZ1SPQFSUZ$IBOHFE interface is used to notify binding clients that propertyvalues have been changed For example, if we had a 6TFS object and it had a /BNF
property, then our 6TFS class would be responsible for raising the 1SPQFSUZ$IBOHFE event
of the */PUJGZ1SPQFSUZ$IBOHFE interface, specifying the name of the property each timeits value was changed We'll look much deeper into all of this later, but now let's see howthe arrangement of these components help us
So how does MVVM help?
One major benefit of adopting MVVM is that it provides the crucial Separation of Concernsbetween the business model, the UI, and the business logic This enables us to do severalthings It frees the View Models from the Models, both the business model and the datapersistence technology This in turn enables us to reuse the business model in other
applications and swap out the DAL and replace it with a mock data layer so that we caneffectively test the functionality in our view models without requiring any kind of real dataconnection
It also disconnects the Views from the View logic that they require, as this is provided bythe View Models This allows us to run each component independently, which has theadvantage of enabling one team to work on designing the Views, while another team works
on the View Models Having parallel work streams enables companies to benefit fromvastly reduced production times
Furthermore, this separation also makes it easier for us to swap the Views for a differenttechnology without needing to change our Model code We may well need to change someaspects of the View Models, for example, the new technology used for the Views may notsupport the *$PNNBOE interface, but in principal, the amount of code that we would need tochange would be fairly minimal
The simplicity of the MVVM pattern also makes WPF easier to comprehend Knowing thateach View has a View Model that provides it with all the data and functionality that itrequires means that we always know where to look when we want to find where our databound properties have been declared
Trang 25Is there a downside?
There are, however, a few drawbacks to using MVVM, and it will not help us in everysituation The main downside to implementing MVVM is that it adds a certain level ofcomplexity to our applications First, there's the data binding, which can take some time tomaster Also, depending on your version of Visual Studio, data binding errors may onlyappear at runtime and can be very tricky to track down
Then, there are the different ways to communicate between the Views and View Modelsthat we need to understand Commanding and handling events in an unusual way takes awhile to get used to Having to discover the optimal arrangement of all the required
components in the code base also takes time So, there is a steep learning curve to climbbefore we can become competent at implementing MVVM for sure This book will cover all
of these areas in detail and attempt to lessen the gradient of that learning curve
However, even when we are well practiced at the pattern, there are still occasional
situations when it wouldn't make sense to implement MVVM One example would be if ourapplication was going to be very small, it would be unlikely that we would want to haveunit tests for it or swap out any of its components It would, therefore, be impractical to gothrough the added complexity of implementing the pattern when the benefits of the
Separation of Concerns that it provides were not required
Debunking the myth about code behind
One of the great misconceptions about MVVM is that we should avoid putting any codeinto the code behind files of our Views While there is some truth to this, it is certainly nottrue in all situations If we think logically for a moment, we already know that the mainreason to use MVVM is to take advantage of the Separation of Concerns that its architectureprovides Part of this separates the business functionality in the View Model from the userinterface-related code in the Views Therefore, the rule should really be we should avoidputting any business logic into the code behind files of our Views
Keeping this in mind, let's look at what code we might want to put into the code behind file
of a View The most likely suspects would be some UI-related code, maybe handling aparticular event, or launching a child window of some kind In these cases, using the codebehind file would be absolutely fine We have no business-related code here, and so wehave no need to separate it from the other UI-related code
Trang 26A Smarter Way of Working with WPF
[ 13 ]
On the other hand, if we had written some business-related code in a View's code behindfile, then how could we test it? In this case, we would have no way to separate this from theView, no longer have our Separation of Concerns and, therefore, would have broken ourimplementation of MVVM So in cases like this, the myth is no longer a mytha it is goodadvice
However, even in cases like this where we want to call some business-related code from a
View, it is possible to achieve without breaking any rules As long as our business code
resides in a View Model, it can be tested through that View Model, so it's not so importantwhere it is called from during runtime Understanding that we can always access the ViewModel that is data bound to a View's %BUB$POUFYU property, let's look at this simple
If it is likely, then we really shouldn't put this code into the code behind file and insteadhandle the event by wrapping it in an Attached Property, and we'll see an example of this inthe next section However, if it is not at all likely, then there is really no problem withputting it there Let's follow rules when they make sense for us to follow them rather thanblindly sticking to them because somebody in a different scenario said they were a goodidea
One other situation when we can ignore this 'No code behind' rule is when writing contained controls based on the 6TFS$POUSPM class In these cases, the code behind files areoften used for defining Dependency Properties and/or handling UI events and for
self-implementing general UI functionality Remember though, if these controls are
implementing some business-related functionality, we should write that into a View Modeland call it from the control so that it can still be tested
There is definitely perfect sense in the general idea of avoiding writing business-relatedcode in the code behind files of our Views and we should always try to do so However, wenow hopefully understand the reasoning behind this idea and can use our logic to
determine whether it is ok to do it or not in each particular case that may arise
Trang 27Learning how to communicate again
As we tend not to handle UI events directly, when using MVVM, we need alternative ways
to implement the same functionality that they provide Different methods are required toreproduce the functionality of different events For example, the functionality of the
4FMFDUJPO$IBOHFE event of a collection control is typically reproduced by data binding aView Model property to the 4FMFDUFE*UFN property of the collection control
-JTU#PY*UFNT4PVSDF\#JOEJOH*UFNT^
4FMFDUFE*UFN\#JOEJOH$VSSFOU*UFN^
In this example, the setter of the $VSSFOU*UFN property will get called by the WPF
Framework each time a new item is selected from the -JTU#PY Therefore, instead of
handling the 4FMFDUJPO$IBOHFE event in the code behind, we can call any method directlyfrom the property setter in the View Model:
Many other UI events can be replaced with some form of 5SJHHFS in the XAML markupdirectly For example, imagine that we had an *NBHF element that was set as the $POUFOUproperty value of a #VUUPO control and that we wanted the *NBHF element to be semi-transparent when the #VUUPO was disabled Instead of handling the
6*&MFNFOU*T&OBCMFE$IBOHFE event in the code behind file, we could write a
%BUB5SJHHFS in a 4UZMF that we could apply to the *NBHF element:
Trang 28A Smarter Way of Working with WPF
Binding syntax will be covered in detail in $IBQUFS, Becoming Proficient With Data Binding,
but in short, the binding in this %BUB5SJHHFS is specifying the target as the *T&OBCMFEproperty of the ancestor (or parent) of the *NBHF element with a type of #VUUPO When thisbinding target has a value of 'BMTF, the 0QBDJUZ property of the *NBHF will be set to and set back to its original value when the target property value is 5SVF Therefore, the
*NBHF element in our #VUUPO will become semi-transparent when the #VUUPO is disabled
Introducing the ICommand interface
When it comes to button clicks in WPF and MVVM, instead of handling the well-known
$MJDL event, we typically use some form of command that implements the *$PNNBOEinterface Let's take a look at an example of a basic standard command:
Trang 29We can see that it has an &YFDVUF method, where the functionality that the commandprovides is performed The $BO&YFDVUF method is called by the $PNNBOE.BOBHFS atvarious points over time, when it believes that the output value may have changed We'llcover this in more detail later, but basically, raising the $BO&YFDVUF$IBOHFE event is one
of the ways to trigger the $PNNBOE.BOBHFS to do this The output of the $BO&YFDVUFmethod specifies whether the &YFDVUF method can be called or not
You can imagine how cumbersome it would be if we had to create one of these classes forevery action that we needed to implement Furthermore, there is no context of where thecommand was called from other than the single command parameter This means that if wewanted the command to add an item into a collection, we would have to put both thecollection and the item to add into another object so that they could both be passed throughthe single input parameter
When using MVVM, rather than implementing the commands in the standard way, wetend to use a single, reusable implementation that allows us to handle actions with standardmethods directly in the View Model This enables us to use commands without having tocreate a separate class for each one There are a number of variations of this command, butits simplest form is shown here:
Trang 30A Smarter Way of Working with WPF
A safer way to ensure that the command is never called by code when the $BO&YFDVUF
condition is not satisfied would be to make this alteration; however, please note that the
$PNNBOE.BOBHFS will always perform this check before calling any commands anyway:
The BDUJPO parameter of type "DUJPOPCKFDU will hold the reference to the method thatwill be called when the command is executed and the PCKFDU generic parameter relates tothe optionally used command parameter The DBO&YFDVUF parameter of type
1SFEJDBUFPCKFDU will hold the reference to the method that will be called to verifywhether the command can be executed or not and its PCKFDU generic parameter relates tothe optionally used command parameter again
Trang 31The $BO&YFDVUF$IBOHFE event should be raised whenever the DBO&YFDVUF parametervalue changes It is typically handled by command sources, such as the #VUUPO control, toset their *T&OBCMFE property value appropriately When a command source receives anotification that this event has been raised, it will call the *$PNNBOE$BO&YFDVUF method
to check the new value Therefore, when a command can execute, its data bound controlwill be enabled and when it can't, its data bound control will be disabled
The $PNNBOE.BOBHFS3FRVFSZ4VHHFTUFE event will be raised when the
$PNNBOE.BOBHFS detects a change in the UI that could reflect on whether a commandcould execute or not For example, this could be due to a user interaction, such as the
selection of an item in a collection or some other change in focus Therefore, connecting one
to the other seems to be a logical thing to do In fact, an example of this is actually found inthe source code of the NET 3PVUFE$PNNBOE class We'll look at this "DUJPO$PNNBOE againand in more detail in $IBQUFS, Writing Custom Application Frameworks, but for now, let's
move on to the next method of communication
Handling events in Attached Properties
There is one way to handle events in WPF without having to resort to writing code in thecode behind file of a View Using Attached Properties, we can encapsulate the handling ofevents and effectively expose their behavior using properties that we can data bind to in ourViews Let's take a look at a simple example using the 1SFWJFX,FZ%PXO event:
Trang 32A Smarter Way of Working with WPF
of the 1SPQFSUZ.FUBEBUB constructor
The (FU0O&OUFS,FZ%PXO and 4FU0O&OUFS,FZ%PXO methods represent the normal way toget and set Attached Property values In the unfortunately named
0O0O&OUFS,FZ%PXO$IBOHFE method, which will be called when the property value
changes, we look at the /FX7BMVF and 0ME7BMVF values of the
%FQFOEFODZ1SPQFSUZ$IBOHFE&WFOU"SHT input parameter in order to decide whether weneed to attach or detach the event handler to the '1SFWJFX,FZ%PXO event of the relevant5FYU#PY
If the 0ME7BMVF value is null and the /FX7BMVF value is not null, it means that there was noprevious value, and so the property is being set for the first time In this case, we want toattach the event handler Conversely, when the 0ME7BMVF value is not null and the
/FX7BMVF value is null, it means that there previously was a value, which has been
removed, so we should detach the event handler
Trang 33Finally, the 5FYU#PY@0O&OUFS,FZ%PXO event handling method first detects whether either
the Enter key or the Return key were pressed If one was pressed, the data bound *$PNNBOE
instance is checked for OVMM and if the command can execute, it is then executed Therefore,
we have effectively wrapped a 1SFWJFX,FZ%PXO event in an Attached Property and can
now execute any command that has been data bound to it when the user presses Enter on
their keyboard
In order to use this Attached Property, we must first add an XML namespace prefix for our
"UUBDIFE folder in the XAML file of the View that this functionality is required in Notethat the 5FYU#PY1SPQFSUJFT class will be declared in the "UUBDIFE folder of the Viewsproject and so, its namespace will be as follows:
Making use of delegates
Delegates are very similar to events and, in fact, events can be thought of as a particularkind of delegate They are a very simple tool to use to pass a signal or message from oneplace to another in the program Unlike when creating custom events, we are not forced touse particular input parameters, for example, some form of the &WFOU"SHT class We aretotally unconstrained when creating custom delegates and are able to define our ownmethod signatures, including both input and output parameter types
Trang 34A Smarter Way of Working with WPF
This is where delegates save the day Keeping this example simple initially, let's say that wejust need to notify the parent View Model that a particular change has been made so that itcan refresh the current user's security permissions from a database In this case, we onlyneed to pass a signal, so we can create a delegate with no input or output parameters Wecan declare it in the View Model that will be sending the signal, in this case, the child ViewModel
Note that we define it in the same way that we define an abstract method, except that theBCTUSBDU keyword is replaced with the EFMFHBUF keyword after the access modifier Inshort, a delegate defines a type that references a method with a particular signature Nowthat we have defined our signaling delegate, we need to create a way for elements outsidethe View Model to use it For this, we can simply create a property of the type of our new
delegate in the same View Model:
QVCMJD4JHOBM0O4FDVSJUZ1FSNJTTJPO$IBOHFE\HFUTFU^
As we don't need any property change notifications for this property, we can save ourselvessome typing and take advantage of the NET Auto-Implemented Property syntax Bear inmind that delegates work in a multicast way like events, meaning that we can attach more
handlers for the delegate, and in this example, we would want to do that in the parent ViewModel when the child View is instantiated:
Trang 35Here, we have assigned the 3FGSFTI4FDVSJUZ1FSNJTTJPOT method in the parent ViewModel to be the handler for this delegate Note that we omit the parenthesis and the inputparameters if there were any when attaching the handler Now, you may be wondering,bWhat does the method signature of this handler look like?c, but you already have theanswer to this If you remember, we declared the delegate with the signature of the methodthat we want to handle it Therefore, any method that shares this signature can be a handlerfor this type of delegate:
When calling delegates, we must always remember to check for OVMM before trying to usethem because there may be no handlers attached In our example, we'd call our 4JHOBMdelegate via the 0O4FDVSJUZ1FSNJTTJPO$IBOHFE property at the point that we need tosend the signal from the child View Model, let's say in reaction to a user changing their ownsecurity permissions:
Alternatively, we could do so using the more concise null conditional operator in C#
version 6.0, which calls the delegate's *OWPLF method if it is not null:
Note that we do need to include the parenthesis when calling the delegate in the firstexample even though 0O4FDVSJUZ1FSNJTTJPO$IBOHFE is a property This is because thedelegate type of the property relates to a method and it is that method that we are calling.Please bear in mind that the first of these methods is not thread safe, so if thread safety isimportant for your application, then you will need to use the latter way
Trang 36A Smarter Way of Working with WPF
[ 23 ]
We now have the complete picture, but while it is common to have a signal-sendingdelegate such as this, it is not overly useful because it only passes a signal with no otherinformation In many real-world scenarios, we would typically want to have some sort ofinput parameter so that we could pass some information, rather than just a signal
For example, if we wanted to be notified with details each time a user selected a differentitem from a collection control in the UI, we could add a $VSSFOU*UFN property into ageneric #BTF$PMMFDUJPO class in our application and data bind it to the data boundcollection control's 4FMFDUFE*UFN property This $VSSFOU*UFN property would then becalled by the WPF Framework each time a user makes a new selection, and so we can callour new delegate from its property setter:
Trang 37Structuring the application code base
Now that we have a better understanding of the MVVM pattern, let's look at how we mightimplement it in a WPF application What should the folder structure of our application belike? Clearly, we'll need somewhere to put our Models, Views, and View Models; however,how we arrange them will somewhat depend on the overall size of our application
As we have heard, very small projects do not really suit MVVM because implementing itcan involve a lot of preparation and often, the benefits do not apply For small WPF
applications, we would typically have just one project in our WPF application In thesecases, our classes would be separated into different folders within the single project
With larger scale applications, we arrange our classes in the same basic structure, but asthere are more classes and more chance that we want to reuse some of this code, it makessense to use separate projects instead of folders Either way, our classes should end up withthe same CLR namespaces, as they tend to follow the structure of the application, regardless
of whether those classes were separated using folders or projects
While the CLR namespace in our startup project might be something along the lines of
$PNQBOZ/BNF"QQMJDBUJPO/BNF, the namespace of the classes in the Models componentwould be, or start with, $PNQBOZ/BNF"QQMJDBUJPO/BNF.PEFMT For the purpose of theremainder of this book, we will assume that we are dealing with a large-scale WPF
application and using projects for the separation of our classes
There is nothing in the MVVM pattern that dictates what structure our code base shouldhave, although there are clues We will clearly need 7JFXT and 7JFX.PEFMT projects, butthe PEFMT project is less clearly defined There are several elements within the Modelscomponent of MVVM, but we don't necessarily want to group them all into a single project
in our code base There are other projects that will be required too
Let's visualize some possible structures so that we can get started with building our
application
Trang 38A Smarter Way of Working with WPF
[ 25 ]
Trang 40A Smarter Way of Working with WPF
[ 27 ]
These examples offer an insight into what the project structure of an MVVM-based WPFapplication might look like However, nothing is set in stone and we are free to rename and
to reorganize our application projects as we see fit The important thing is how the
components are connected together rather than the arrangement of the application files.After we have developed a number of WPF applications, we get a feel for which projectnames and which structure we prefer, so I'd suggest trying a few variations and seeingwhich you feel more comfortable working with Of course, some of us may not have theluxury of being able to create or alter the structure of the application that we work on Let'sfirst focus on the projects common to both example structures
We see that the *NBHFT and 3FTPVSDFT folders reside in the startup project While this is
customary, they can technically reside in any project or even in their own project However,
I prefer to keep them in this project because it provides a marginal performance benefit.Typically, when using MVVM, the only other files in the startup project will be the
.BJO8JOEPXYBNM, "QQYBNM (and their constituent code behind files), and BQQDPOGJHfiles
The *NBHFT folder contains the images and icons that are displayed in the UI controls,whereas the 3FTPVSDFT folder normally contains any resource files, such as XML schemas
or text or data files that are used by the application
The next project is named $POWFSUFST and is fairly self-explanatory It only containsclasses that have implemented the *7BMVF$POWFSUFS interface and are used for convertingdata bound values in the Views These classes are all reusable and the DLL from this projectshould be kept up to date and shared amongst our other applications
Both examples show an &YUFOTJPOT project, but this is entirely optional and not a
requirement of the MVVM pattern I just happen to find Extension methods to be an
essential part of NET development, having built up a large collection of invaluable helpermethods After getting used to being able to call "EE on an *&OVNFSBCMF instance or5P0CTFSWBCMF$PMMFDUJPO on a query result for example, I now reuse them in everyapplication We'll see some examples of these in $IBQUFS, Writing Custom Application
Frameworks, $IBQUFS, Implementing Responsive Data Validation, and $IBQUFS, Completing
That Great User Experience.
The next common project that we can see is a project called BOBHFST Others may prefer tocall this &OHJOFT, 4FSWJDFT, or something similar, but that is just a personal preference,and either way, the content will be the same In this project, we typically find a number ofclasses that together provide a wide variety of functionality to the View Models For
example, in this project, we might find classes named &YQPSU.BOBHFS, 'FFECBDL.BOBHFS,)BSE%SJWF.BOBHFS, 8JOEPX.BOBHFS, and so on