{"id":356,"date":"2023-10-20T13:48:12","date_gmt":"2023-10-20T05:48:12","guid":{"rendered":"https:\/\/miie.net\/?p=356"},"modified":"2023-10-20T13:48:12","modified_gmt":"2023-10-20T05:48:12","slug":"pro-c10-chapter-29-wpf-notifications-validations-commands-and-mvvm","status":"publish","type":"post","link":"https:\/\/diji.net\/?p=356","title":{"rendered":"Pro C#10 CHAPTER 29 WPF Notifications, Validations, Commands, and MVVM"},"content":{"rendered":"<p>CHAPTER 29<\/p>\n<p>WPF Notifications, Validations, Commands, and MVVM<\/p>\n<p>This chapter will conclude your investigation of the WPF programming model by covering the capabilities that support the Model-View-ViewModel (MVVM) pattern. The first section covers the Model-View- ViewModel pattern. Next, you learn about the WPF notification system and its implementation of the Observable pattern through observable models and observable collections. Having the data in the UI accurately portray the current state of the data automatically improves the user experience significantly and reduces the manual coding required in older technologies (such as WinForms) to achieve the same result.<br \/>\nBuilding on the Observable pattern, you will examine the mechanisms to add validation into your application. Validation is a vital part of any application\u2014not only letting the user know that something is wrong but also letting them know what is wrong. To inform the user what the error is, you will also learn how to incorporate validation into the view markup.<br \/>\nNext, you will take a deeper dive into the WPF command system and create custom commands to encapsulate program logic, much as you did in Chapter 25 with the built-in commands. There are several advantages to creating custom commands, including (but not limited to) enabling code reuse, logic encapsulation, and separation of concerns.<br \/>\nFinally, you will bring all of this together in a sample MVVM application.<\/p>\n<p>Introducing Model-View-ViewModel<br \/>\nBefore you dive into notifications, validations, and commands in WPF, it would be good to understand the end goal of this chapter, which is the Model-View-ViewModel pattern (MVVM). Derived from Martin<br \/>\nFowler\u2019s Presentation Model pattern, MVVM leverages XAML-specific capabilities, discussed in this chapter, to make your WPF development faster and cleaner. The name itself describes the main components of the pattern: model, view, view model.<\/p>\n<p>The Model<br \/>\nThe model is the object representation of your data. In MVVM, models are conceptually the same as the models from your data access layer (DAL). Sometimes they are the same physical class, but there is no requirement for this. As you read this chapter, you will learn how to decide whether you can use your DAL models or whether you need to create new ones.<br \/>\nModels typically take advantage of the built-in (or custom) validations through data annotations and the INotifyDataErrorInfo interface and are configured as observable to tie into the WPF notification system. You will see all of this later in this chapter.<\/p>\n<p>\u00a9 Andrew Troelsen, Phil Japikse 2022<br \/>\nA. Troelsen and P. Japikse, Pro C# 10 with .NET 6, <a href=\"https:\/\/doi.org\/10.1007\/978-1-4842-7869-7_29\"><a href=\"https:\/\/doi.org\/10.1007\/978-1-4842-7869-7_29\"><a href=\"https:\/\/doi.org\/10.1007\/978-1-4842-7869-7_29\">https:\/\/doi.org\/10.1007\/978-1-4842-7869-7_29<\/a><\/a><\/a><\/p>\n<p>1273<\/p>\n<p>The View<br \/>\nThe view is the UI of the application, and it is designed to be very lightweight. Think of the menu board at a drive-thru restaurant. The board displays menu items and prices, and it has a mechanism so the user can communicate with the back-end systems. However, there isn\u2019t any intelligence built into the board, unless it is specifically user interface logic, such as turning on the lights if it gets dark.<br \/>\nMVVM views should be developed with the same goals in mind. Any intelligence should be built into the application elsewhere. The only code in the code-behind file (e.g., MainWindow.xaml.cs) should be directly related to manipulating the UI. It should not be based on business rules or anything that needs to be persisted for future use. While not a main goal of MVVM, well-developed MVVM applications typically have very little code in the code-behind.<\/p>\n<p>The View Model<br \/>\nIn WPF and other XAML technologies, the view model serves two purposes.<br \/>\n\u2022The view model provides a single stop for all the data needed by the view. This doesn\u2019t mean the view model is responsible for getting the actual data; instead, it is merely a transport mechanism to move the data from the data store to the view. Usually, there is a one-to-one correlation between views and view models, but architectural differences exist, and your mileage may vary.<br \/>\n\u2022The second job is to act as the controller for the view. Just like the menu board, the view model takes direction from the user and relays that call to the relevant code to make sure the proper actions are taken. Quite often this code is in the form of custom commands.<\/p>\n<p>Anemic Models or Anemic View Models<br \/>\nIn the early days of WPF, when developers were still working out how best to implement the MVVM pattern, there were significant (and sometimes heated) discussions about where to implement items like validation and the Observable pattern. One camp (the anemic model camp) argued that it all should be in the view model since adding those capabilities to the model broke separation of concerns. The other camp (the anemic view model camp) argued it should all be in the models since that reduced duplication of code.<br \/>\nThe real answer is, of course, it depends. When INotifyPropertyChanged, IDataErrorInfo, and INotifyDataErrorInfo are implemented on the model classes, this ensures that the relevant code is close to the target of the code (as you will see in this chapter) and is implemented only once for each model.<br \/>\nThat being said, there are times when your view model classes will need to be developed as observables themselves. At the end of the day, you need to determine what makes the most sense for your application, without over-complicating your code or sacrificing the benefits of MVVM.<\/p>\n<p>\u25a0Note There are multiple MVVM frameworks available for WPF, such as MVVMLite, Caliburn.Micro, and Prism (although Prism is much more than just an MVVM framework). This chapter discusses the MVVM pattern and the features in WPF that support implementing the pattern. I leave it to you, the reader, to examine the different frameworks and select the one that best matches your app\u2019s needs.<\/p>\n<p>The WPF Binding Notification System<br \/>\nA significant shortcoming in the binding system for WinForms is a lack of notifications. If the data represented in the view is updated programmatically, the UI must also be refreshed programmatically to keep them in sync. This leads to a lot of calls to Refresh() on controls, typically more than are absolutely necessary in order to be safe. While usually not a significant performance issue to include too many calls to Refresh(), if you don\u2019t include enough, the experience for the user could be affected negatively.<br \/>\nThe binding system built into XAML-based applications corrects this problem by enabling you to hook your data objects and collections into a notification system by developing them as observables. Whenever a property\u2019s value changes on an observable model or the collection changes (e.g., items are added, removed, or reordered) on an observable collection, an event is raised (either NotifyPropertyChanged<br \/>\nor NotifyCollectionChanged). The binding framework automatically listens for those events to occur<br \/>\nand updates the bound controls when they fire. Even better, as a developer, you have control over which properties raise the notifications. Sounds perfect, right? Well, it\u2019s not quite perfect. There can be a fair amount of code involved in setting this up for observable models if you are doing it all by hand. Fortunately, there is an open source framework that makes it much simpler, as you shall soon see.<\/p>\n<p>Observable Models and Collections<br \/>\nIn this section, you will create an application that uses observable models and collections. To get started, create a new WPF application named WpfNotifications. The application will be a master-detail form, allowing the user to select a specific car using a ComboBox, and then the details for that car will be displayed in the following TextBox controls. Update MainWindow.xaml by replacing the default Grid with the following markup:<\/p>\n<p><Grid IsSharedSizeScope=\"True\" Margin=\"5,0,5,5\"><br \/>\n<Grid.RowDefinitions><br \/>\n<RowDefinition Height=\"Auto\"\/><br \/>\n<RowDefinition Height=\"Auto\"\/><br \/>\n<\/Grid.RowDefinitions><br \/>\n<Grid Grid.Row=\"0\"><br \/>\n<Grid.ColumnDefinitions><br \/>\n<ColumnDefinition Width=\"Auto\" SharedSizeGroup=\"CarLabels\"\/><br \/>\n<ColumnDefinition Width=\"*\"\/><br \/>\n<\/Grid.ColumnDefinitions><br \/>\n<Label Grid.Column=\"0\" Content=\"Vehicle\"\/><br \/>\n<ComboBox Name=\"cboCars\" Grid.Column=\"1\" DisplayMemberPath=\"PetName\" \/><br \/>\n<\/Grid><br \/>\n<Grid Grid.Row=\"1\" Name=\"DetailsGrid\"><br \/>\n<Grid.ColumnDefinitions><br \/>\n<ColumnDefinition Width=\"Auto\" SharedSizeGroup=\"CarLabels\"\/><br \/>\n<ColumnDefinition Width=\"*\"\/><br \/>\n<\/Grid.ColumnDefinitions><br \/>\n<Grid.RowDefinitions><br \/>\n<RowDefinition Height=\"Auto\"\/><br \/>\n<RowDefinition Height=\"Auto\"\/><br \/>\n<RowDefinition Height=\"Auto\"\/><\/p>\n<p><RowDefinition Height=\"Auto\"\/><br \/>\n<RowDefinition Height=\"Auto\"\/><br \/>\n<\/Grid.RowDefinitions><br \/>\n<Label Grid.Column=\"0\" Grid.Row=\"0\" Content=\"Id\"\/><br \/>\n<TextBox Grid.Column=\"1\" Grid.Row=\"0\" \/><br \/>\n<Label Grid.Column=\"0\" Grid.Row=\"1\" Content=\"Make\"\/><br \/>\n<TextBox Grid.Column=\"1\" Grid.Row=\"1\" \/><br \/>\n<Label Grid.Column=\"0\" Grid.Row=\"2\" Content=\"Color\"\/><br \/>\n<TextBox Grid.Column=\"1\" Grid.Row=\"2\" \/><br \/>\n<Label Grid.Column=\"0\" Grid.Row=\"3\" Content=\"Pet Name\"\/><br \/>\n<TextBox Grid.Column=\"1\" Grid.Row=\"3\" \/><br \/>\n<StackPanel Grid.Column=\"0\" Grid.ColumnSpan=\"2\" Grid.Row=\"4\" HorizontalAlignment=\"Right\" Orientation=\"Horizontal\" Margin=\"0,5,0,5\"><br \/>\n<Button x:Name=\"btnAddCar\" Content=\"Add Car\" Margin=\"5,0,5,0\" Padding=\"4, 2\" \/><br \/>\n<Button x:Name=\"btnChangeColor\" Content=\"Change Color\" Margin=\"5,0,5,0\" Padding=\"4, 2\"\/><br \/>\n<\/StackPanel><br \/>\n<\/Grid><br \/>\n<\/Grid><\/p>\n<p>Your window will resemble Figure 29-1.<\/p>\n<p>Figure 29-1. Master-detail window displaying Car details<\/p>\n<p>The IsSharedSizeScope tag on the Grid control sets up child grids to share dimensions. The ColumnDefinitions marked SharedSizeGroup will automatically be sized to the same width without any programming needed. In this example, if the Pet Name label was changed to something much longer, the Vehicle column (which is in a different Grid control) would be sized to match it, keeping the window\u2019s appearance nice and tidy.<br \/>\nNext, right-click the project name in Solution Explorer, select Add \u27a4 New Folder, and name the folder<br \/>\nModels. In this new folder, create a class named Car. The initial class is listed here:<\/p>\n<p>public class Car<br \/>\n{<br \/>\npublic int Id { get; set; } public string Make { get; set; } public string Color { get; set; }<br \/>\npublic string PetName { get; set; }<br \/>\n}<\/p>\n<p>Adding Bindings and Data<br \/>\nThe next step is to add the binding statements for the controls. Remember that data-binding statements revolve around a data context, and this can be set on the control itself or on a parent control. Here, you are going to set the context on the DetailsGrid, so each control contained will inherit that data context. Set the DataContext to the SelectedItem property of the ComboBox. Update the Grid that holds the detail controls to the following:<\/p>\n<p>&lt;Grid Grid.Row=&quot;1&quot; Name=&quot;DetailsGrid&quot;<br \/>\nDataContext=&quot;{Binding ElementName=cboCars, Path=SelectedItem}&quot;&gt;<\/p>\n<p>The text boxes in the DetailsGrid will show the individual properties of the select car. Add the appropriate text attributes and related bindings to the TextBox controls, like so:<\/p>\n<p><TextBox Grid.Column=\"1\" Grid.Row=\"0\" Text=\"{Binding Path=Id}\" \/><br \/>\n<TextBox Grid.Column=\"1\" Grid.Row=\"1\" Text=\"{Binding Path=Make}\" \/><br \/>\n<TextBox Grid.Column=\"1\" Grid.Row=\"2\" Text=\"{Binding Path=Color}\" \/><br \/>\n<TextBox Grid.Column=\"1\" Grid.Row=\"3\" Text=\"{Binding Path=PetName}\" \/><\/p>\n<p>Finally, add data to the ComboBox. In MainWindow.xaml.cs, create a new list of Car records, and set the ItemsSource for the ComboBox to the list. Also, add the using statement for the Notifications.Models namespace.<\/p>\n<p>using WpfNotifications.Models;<br \/>\n\/\/omitted for brevity<br \/>\npublic partial class MainWindow : Window<br \/>\n{<br \/>\nreadonly IList<Car> _cars = new List<Car>(); public MainWindow()<br \/>\n{<br \/>\nInitializeComponent();<br \/>\n_cars.Add(new Car {Id = 1, Color = &quot;Blue&quot;, Make = &quot;Chevy&quot;, PetName = &quot;Kit&quot;});<br \/>\n_cars.Add(new Car {Id = 2, Color = &quot;Red&quot;, Make = &quot;Ford&quot;, PetName = &quot;Red Rider&quot;}); cboCars.ItemsSource = _cars;<br \/>\n}<br \/>\n}<\/p>\n<p>Run the app. You\u2019ll see that the vehicle selector has two cars to choose from. Choose one of them, and the text boxes will be automatically populated with the vehicle detail. Change the color of one of the vehicles, select the other vehicle, and then go back to the vehicle you edited. You will see the new color is indeed still attached to the vehicle. This isn\u2019t anything remarkable; you\u2019ve seen the power of XAML data binding in previous examples.<\/p>\n<p>Programmatically Changing the Vehicle Data<br \/>\nWhile the previous example works as expected, if the data is changed programmatically, the UI will not reflect the changes unless you program the app to refresh the data. To demonstrate this, add an event handler for the btnChangeColor Button, like so:<\/p>\n<p><Button x:Name=\"btnChangeColor\" Content=\"Change Color\" Margin=\"5,0,5,0\" Padding=\"4, 2\" Click=\"BtnChangeColor_OnClick\"\/><\/p>\n<p>In the BtnChangeColor_Click() event handler, use the SelectedItem property of the ComboBox to locate the selected record from the cars list, and change the color to Pink. The code is listed here:<\/p>\n<p>private void BtnChangeColor_OnClick(object sender, RoutedEventArgs e)<br \/>\n{<br \/>\n_cars.First(x =&gt; x.Id == ((Car)cboCars.SelectedItem)?.Id).Color = &quot;Pink&quot;;<br \/>\n}<\/p>\n<p>Run the app, select a vehicle, and click the Change Color button. Nothing changes visibly. Select the other vehicle and go back to your originally selected vehicle. Now you will see the updated value. This is not a good experience for the user!<br \/>\nNow add an event handler to the btnAddCar button, like this:<\/p>\n<p><Button x:Name=\"btnAddCar\" Content=\"Add Car\" Margin=\"5,0,5,0\" Padding=\"4, 2\" Click=\"BtnAddCar_OnClick\" \/><\/p>\n<p>In the BtnAddCar_Click event handler, add a new record to the Car list.<\/p>\n<p>private void BtnAddCar_Click(object sender, RoutedEventArgs e)<br \/>\n{<br \/>\nvar maxCount = _cars?.Max(x =&gt; x.Id) ?? 0;<br \/>\n_cars?.Add(new Car { Id=++maxCount,Color=&quot;Yellow&quot;,Make=&quot;VW&quot;,PetName=&quot;Birdie&quot;});<br \/>\n}<\/p>\n<p>Run the app, click the Add Car button, and examine the contents of the ComboBox. Even though you know there are three cars in the list, only two are displayed! To correct both of these problems, you will convert the Car class to an observable model and use an observable collection to hold all the Car instances.<\/p>\n<p>Observable Models<br \/>\nThe problem of data changing on a property of your model and not being displayed in the UI is resolved by implementing the INotifyPropertyChanged interface on your Car model class. The INotifyPropertyChanged interface contains a single event: PropertyChangedEvent. The XAML binding engine listens for this event for each bound property on classes that implement the INotifyPropertyChanged interface. The interface is shown here:<\/p>\n<p>public interface INotifyPropertyChanged<br \/>\n{<br \/>\nevent PropertyChangedEventHandler PropertyChanged;<br \/>\n}<\/p>\n<p>Add the following using statements to the Car.cs class:<\/p>\n<p>using System.ComponentModel;<br \/>\nusing System.Runtime.CompilerServices;<\/p>\n<p>Next, implement the INotifyPropertyChanged interface on the class, as follows:<\/p>\n<p>public class Car : INotifyPropertyChanged<br \/>\n{<br \/>\n\/\/Omitted for brevity<br \/>\npublic event PropertyChangedEventHandler PropertyChanged;<br \/>\n}<\/p>\n<p>The PropertyChanged event takes an object reference and a new instance of the<br \/>\nPropertyChangedEventArgs class, like in this example:<\/p>\n<p>PropertyChanged?.Invoke(this,<br \/>\nnew PropertyChangedEventArgs(&quot;Model&quot;));<\/p>\n<p>The first parameter is the object instance that is raising the event. The PropertyChangedEventArgs constructor takes a string that indicates the property that was changed and needs to be updated. When the event is raised, the binding engine looks for any controls bound to the named property on that instance. If you pass String.Empty into the PropertyChangedEventArgs, all of the bound properties of the instance are updated.<br \/>\nYou control which properties are enlisted in the automatic updates. Only those properties that raise the PropertyChanged event in the setter will be automatically updated. This is usually all the properties on your model classes, but you have the option of omitting certain properties based on your application\u2019s requirements. Instead of raising the event directly in the setter for each of the enlisted properties, a common pattern is to create a helper method (typically named OnPropertyChanged()) that raises the event on behalf of the properties, usually in a base class for your models. Add the following method and code into the Car.cs class:<\/p>\n<p>protected void OnPropertyChanged([CallerMemberName] string propertyName = &quot;&quot;)<br \/>\n{<br \/>\nPropertyChanged?.Invoke(this,<br \/>\nnew PropertyChangedEventArgs(propertyName));<br \/>\n}<\/p>\n<p>Next, update each of the automatic properties in the Car class to have a full getter and setter with a backing field. When the value is changed, call the OnPropertyChanged() helper method. Here is the Id property updated:<\/p>\n<p>private int _id; public int Id<br \/>\n{<br \/>\nget =&gt; _id; set<br \/>\n{<br \/>\nif (value == _id) return;<br \/>\n_id = value;<br \/>\nOnPropertyChanged();<br \/>\n}<br \/>\n}<\/p>\n<p>Make sure you do the same for all the properties in the class and then run the app again. Select a vehicle and click the Change Color button. You will immediately see the change show up in the UI. First problem solved!<\/p>\n<p>Using nameof<br \/>\nA feature added in C# 6 is the nameof operator, which provides the string name of the item passed into the<br \/>\nnameof method. You can use this in the calls to OnPropertyChanged() in your setters, like this:<\/p>\n<p>public string Color<br \/>\n{<br \/>\nget { return _color; } set<br \/>\n{<br \/>\nif (value == _color) return;<br \/>\n_color = value; OnPropertyChanged(nameof(Color));<br \/>\n}<br \/>\n}<\/p>\n<p>Note that you don\u2019t have to remove the CallerMemberName attribute from OnPropertyChanged() when you use the nameof method (although it becomes unnecessary). In the end, whether you use the nameof method or the CallerMemberName attribute comes down to a matter of personal choice.<\/p>\n<p>Observable Collections<br \/>\nThe next problem to resolve is updating the UI when the contents of a collection changes. This is done by implementing the INotifyCollectionChanged interface. Like the INotifyPropertyChanged interface, this interface exposes one event, the CollectionChanged event. Unlike the INotifyPropertyChanged event, implementing this interface by hand is more than just calling a method in the setter. You need to create a full List implementation and raise the CollectionChanged event any time your list changes.<\/p>\n<p>Using the ObservableCollections Class<br \/>\nFortunately, there is a much easier way than creating your own collection class. The ObservableCollection<T> class implements INotifyCollectionChanged, INotifyPropertyChanged, and Collection<T>, and it is part of the .NET Core Framework. No extra work! To see this, add a using statement for System.Collections.ObjectModel and then update the private field for _cars to the following:<\/p>\n<p>private readonly IList<Car> _cars = new ObservableCollection<Car>();<\/p>\n<p>Run the app again and click the Add Car button. You will see the new records appear appropriately.<\/p>\n<p>Implementing a Dirty Flag<br \/>\nAnother advantage of observable models is the ability to track state changes. Dirty tracking (tracking when one or more of an object\u2019s values have changed) with WPF is fairly trivial. Add a bool property named IsChanged to the Car class. Make sure to call OnPropertyChanged() just like the other properties in the Car class.<\/p>\n<p>private bool _isChanged; public bool IsChanged {<br \/>\nget =&gt; _isChanged; set<br \/>\n{<br \/>\nif (value == _isChanged) return;<br \/>\n_isChanged = value;<br \/>\nOnPropertyChanged();<br \/>\n}<br \/>\n}<\/p>\n<p>You need to set the IsChanged property to true in the OnPropertyChanged() method. You also need to make sure you aren\u2019t setting IsChanged to true when IsChanged is updated, or you will hit a stack overflow exception! Update the OnPropertyChanged() method to the following (which uses the nameof method discussed earlier):<\/p>\n<p>protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = &quot;&quot;)<br \/>\n{<br \/>\nif (propertyName != nameof(IsChanged))<br \/>\n{<br \/>\nIsChanged = true;<br \/>\n}<br \/>\nPropertyChanged?.Invoke(this,<br \/>\nnew PropertyChangedEventArgs(propertyName));<br \/>\n}<\/p>\n<p>Open MainWindow.xaml and add an additional RowDefinition to the DetailsGrid. Add the following to the end of the Grid, which contains a Label and a CheckBox, bound to the IsChanged property, as follows:<\/p>\n<p><Label Grid.Column=\"0\" Grid.Row=\"5\" Content=\"Is Changed\"\/><br \/>\n<CheckBox Grid.Column=\"1\" Grid.Row=\"5\" VerticalAlignment=\"Center\" Margin=\"10,0,0,0\" IsEnabled=\"False\" IsChecked=\"{Binding Path=IsChanged}\" \/><\/p>\n<p>If you were to run the app now, you would see that every single record shows up as changed, even though you haven\u2019t changed anything! This is because object creation sets property values, and setting any values calls OnPropertyChanged(). This sets the object\u2019s IsChanged property. To correct this, set the<br \/>\nIsChanged property to false as the last property in the object initialization code. Open MainWindow.xaml.cs<br \/>\nand change the code that creates the list to the following:<\/p>\n<p>_cars.Add(<br \/>\nnew Car {Id = 1, Color = &quot;Blue&quot;, Make = &quot;Chevy&quot;, PetName = &quot;Kit&quot;, IsChanged = false});<br \/>\n_cars.Add(<br \/>\nnew Car {Id = 2, Color = &quot;Red&quot;, Make = &quot;Ford&quot;, PetName = &quot;Red Rider&quot;, IsChanged = false});<\/p>\n<p>Run the app again, select a vehicle, and click the Change Color button. You will see the check box get selected along with the updated color.<\/p>\n<p>Updating the Source Through UI Interaction<br \/>\nYou might notice that if you type text into the UI, the Is Changed check box doesn\u2019t actually get selected until you tab out of the control being edited. This is because of the UpdateSourceTrigger property on the TextBox bindings. The UpdateSourceTrigger determines what event (such as changing the value, tabbing out, etc.) causes the UI to update the underlying data. There are four options, as shown in Table 29-1.<\/p>\n<p>Table 29-1. UpdateSourceTrigger Values<\/p>\n<p>Member  Meaning in Life<br \/>\nDefault Sets to the default for the control (e.g., LostFocus for TextBox controls).<br \/>\nExplicit    Updates the source object only when the UpdateSource method is called.<br \/>\nLostFocus   Updates when the control loses focus. This is the default for TextBox controls.<br \/>\nPropertyChanged Updates as soon as the property changes. This is the default for CheckBox controls.<\/p>\n<p>The default source trigger for a TextBox is the LostFocus event. Change this to PropertyChanged by updating the binding for the Color TextBox to the following XAML:<\/p>\n<p><TextBox Grid.Column=\"1\" Grid.Row=\"2\" Text=\"{Binding Path=Color, UpdateSourceTrigger=Proper tyChanged}\" \/><\/p>\n<p>Now, when you run the app and start typing into the Color text box, the check box is immediately selected. You might ask why the default is set to LostFocus for TextBox controls. Any validation (covered in a moment) for a model fires in conjunction with the UpdateSourceTrigger. For a TextBox, this would then potentially cause errors continually flashing until the user entered the correct values. For example, if the validation rules don\u2019t allow less than five characters in a TextBox, the error would show on each keystroke until the user got five or more entered. In those cases, it\u2019s best to wait for the user to tab out of the TextBox (after completing the change to the text) to update the source.<\/p>\n<p>Wrapping Up Notifications and Observables<br \/>\nUsing INotifyPropertyChanged on your models and ObservableCollections classes for your lists improves the user experience by keeping the data and the UI in sync. While neither interface is complicated, they<br \/>\ndo require updates to your code. Fortunately, Microsoft has included the ObservableCollection class to handle all of the plumbing to create observable collections. Just as fortunate is the update to the Fody project to add INotifyPropertyChanged functionality automatically. With these two tools in hand, there isn\u2019t any reason to not implement observables in your WPF applications.<\/p>\n<p>WPF Validations<br \/>\nNow that you\u2019ve implemented INotifyPropertyChanged and are using an ObservableCollection, it\u2019s time to add validations to your application. Applications need to validate user input and provide feedback to the user when the data entered is incorrect. This section covers the most common validation mechanisms for modern WPF applications, but these are still just a portion of the capabilities built into WPF.<\/p>\n<p>Validation occurs when a data binding attempts to update the data source. In addition to built-in validations, such as exceptions in a property\u2019s setter, you can create custom validation rules. If any validation rule (built-in or custom) fails, the Validation class, discussed shortly, comes into play.<\/p>\n<p>\u25a0Note  For each of the sections in this chapter, you can continue working in the same project from the previous section, or you can create a copy of the project for each new section. In the repo for this chapter, each section is a different project.<\/p>\n<p>Updating the Sample for the Validation Examples<br \/>\nIn the repo for this chapter, the new project (copied from the previous example) is called WpfValidations. If you are using the same project from the previous section, you just need to make note of the namespace changes when copying code into your project from the examples listed in this section.<\/p>\n<p>The Validation Class<br \/>\nBefore adding validations to your project, it\u2019s important to understand the Validation class. This class is part of the validation framework, and it provides methods and attached properties that can be used to<br \/>\ndisplay validation results. There are three main properties of the Validation class commonly used when handling validation errors (shown in Table 29-2). You will use each of these through the rest of this section.<\/p>\n<p>Table 29-2. Key Members of the Validation Class<\/p>\n<p>Member  Meaning in Life<br \/>\nHasError    Attached property indicating that a validation rule failed somewhere in the process<br \/>\nErrors  Collection of all active ValidationError objects<br \/>\nErrorTemplate   Control template that becomes visible and adorns the bound element when HasError is set to true<\/p>\n<p>Validation Options<br \/>\nAs mentioned, XAML technologies have several mechanisms for incorporating validation logic into your application. You will examine three of the most commonly used validation choices in the next sections.<\/p>\n<p>Notify on Exceptions<br \/>\nWhile exceptions should not be used to enforce business logic, exceptions can and do happen, and they should be handled appropriately. In case they aren\u2019t handled in code, the user should receive visual feedback of the problem. An important change from WinForms is that WPF binding exceptions are not, by default, propagated to the user as exceptions. They are, however, visually indicated, using an adorner (visual layer that resides on top of your controls).<\/p>\n<p>To test this, run the app, select a record from the ComboBox, and clear out the Id value. Since the Id property is defined as an int (not a nullable int), a numeric value is required. When you tab out of the Id field, an empty string is sent to the Id property by the binding framework, and since an empty string can\u2019t be converted to an int, an exception is thrown in the setter. Normally, an unhandled exception would generate a message box to the user, but in this case, nothing like that happened. If you look in the Debug portion of the Output window, you will see the following:<\/p>\n<p>System.Windows.Data Error: 7 : ConvertBack cannot convert value '' (type 'String'). BindingExpression:Path=Id; DataItem='Car' (HashCode=52579650); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String') FormatException:'System. FormatException: Input string was not in a correct format.<\/p>\n<p>Visual display of the exception is a thin red box around the control, as shown in Figure 29-2.<\/p>\n<p>Figure 29-2. The default error template<\/p>\n<p>The red box is the ErrorTemplate property of the Validation object and acts as an adorner for the bound control. While the default error adorner shows that there is indeed an error, there isn\u2019t any indication as to what is wrong. The good news is that the ErrorTemplate is completely customizable, as you will see later in this chapter.<\/p>\n<p>IDataErrorInfo<br \/>\nThe IDataErrorInfo interface provides a mechanism for you to add custom validations to your model classes. This interface is added directly to your model (or view model) classes, and the validation code is placed inside your model classes (preferably in partial classes). This centralizes validation code in your project, in direct contrast to WinForms projects, where validation was typically done in the UI itself.<\/p>\n<p>The IDataErrorInfo interface, shown here, contains two properties: an indexer and a string property named Error. Note that the WPF binding engine doesn\u2019t use the Error property.<\/p>\n<p>public interface IDataErrorInfo<br \/>\n{<br \/>\nstring this[string columnName] { get; } string Error { get; }<br \/>\n}<\/p>\n<p>You will be adding the Car partial class shortly, but first you need to update the Car.cs class and mark it as partial. Next, add another file to the Models directory named CarPartial.cs. Rename this class Car, make sure the class is marked as partial, and add the IDataErrorInfo interface. Finally, implement the API for the interface. The initial code is listed here:<\/p>\n<p>public partial class Car : IDataErrorInfo<br \/>\n{<br \/>\npublic string this[string columnName] =&gt; string.Empty; public string Error { get;}<br \/>\n}<\/p>\n<p>For a bound control to opt in to the IDataErrorInfo interface, it must add ValidatesOnDataErrors to the binding expression. Update the binding expression for the Make text box to the following (and update the rest of the binding statements in the same way):<\/p>\n<p><TextBox Grid.Column=\"1\" Grid.Row=\"1\" Text=\"{Binding Path=Make,\nValidatesOnDataErrors=True}\" \/><\/p>\n<p>Once this update is made to the binding statements, the indexer on the model gets called each time the<br \/>\nPropertyChanged event is raised. The property name from the event is used as the columnName parameter in the indexer. If the indexer returns string.Empty, the framework assumes that all validations passed, and no error condition exists. If the indexer returns anything but string.Empty, an error is presumed to exist on the property for that object instance, and each control that is bound to the property being validated on this specific instance of the class is considered to have an error, the HasError property of the Validation object is set to true, and the ErrorTemplate adorner is activated for the controls effected.<br \/>\nNext, you will add some simple validation logic to the indexer in CarPartial.cs. The validation rules are simple.<br \/>\n\u2022If Make equals ModelT, set the error equal to &quot;Too Old&quot;.<br \/>\n\u2022If Make equals Chevy and Color equals Pink, set the error equal to $&quot;{Make}'s don't come in {Color}&quot;.<br \/>\nStart by adding a switch statement for each of the properties. To avoid using magic strings in the case statements, you will again use the nameof method. If the code falls through the switch statement, return string.Empty. Next, add the validation rules. In the proper case statements, add a check of the property value based on the rules listed earlier. In the case statement for the Make property, first check to make sure the value isn\u2019t ModelT. If it is, return the error. If that passes, the next line will call into a helper method that returns an error if the second rule is violated, or it will return string.Empty if it is not. In the case statement for the Color property, also call the helper method. The code is as follows:<\/p>\n<p>public string this[string columnName]<br \/>\n{<br \/>\nget<br \/>\n{<br \/>\nswitch (columnName)<br \/>\n{<br \/>\ncase nameof(Id):<br \/>\nbreak;<br \/>\ncase nameof(Make):<br \/>\nreturn Make == &quot;ModelT&quot;<br \/>\n? \u201cToo Old\u201d<br \/>\n: CheckMakeAndColor(); case nameof(Color):<br \/>\nreturn CheckMakeAndColor(); case nameof(PetName):<br \/>\nbreak;<br \/>\n}<br \/>\nreturn string.Empty;<br \/>\n}<br \/>\n}<\/p>\n<p>internal string CheckMakeAndColor()<br \/>\n{<br \/>\nif (Make == &quot;Chevy&quot; &amp;&amp; Color == &quot;Pink&quot;)<br \/>\n{<br \/>\nreturn $&quot;{Make}'s don't come in {Color}&quot;;<br \/>\n}<br \/>\nreturn string.Empty;<br \/>\n}<\/p>\n<p>Run the app, select the Red Rider vehicle (the Ford), and change the Make to ModelT. Once you tab out of the field, the red error decorator appears. Now select Kit (which is a Chevy) from the drop-down and<br \/>\nclick the Change Color button to change the color to Pink. Immediately the red error adorner appears on the Color field but doesn\u2019t appear on the Make text box. Now, change Make to Ford, tab out of the text box, and note that the red adorner does not disappear!<br \/>\nThis is because the indexer runs only when the PropertyChanged event is fired for a property. As discussed in earlier, the PropertyChanged event fires when the source object\u2019s property changes, and this happens either through code (such as clicking the Change Color button) or through user interaction (the timing of this is controlled through the UpdateSourceTrigger). When you changed the color, the Make property did not change, so the event did not fire for the Make property. Since the event didn\u2019t fire, the indexer did not get called, so the validation for the Make property didn\u2019t run.<br \/>\nThere are two ways to fix this. The first is to change PropertyChangedEventArgs to update every bound property by passing in string.Empty instead of a field name. As discussed, this causes the binding engine to update every property on that instance. Update the OnPropertyChanged() method in the Car.cs class like this:<\/p>\n<p>protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = &quot;&quot;)<br \/>\n{<br \/>\nif (propertyName != nameof(IsChanged))<br \/>\n{<br \/>\nIsChanged = true;<br \/>\n}<\/p>\n<p>\/\/PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); PropertyChanged?.Invoke(this,<br \/>\nnew PropertyChangedEventArgs(string.Empty));<br \/>\n}<\/p>\n<p>Now, when you run the same test, you see that both the Make and Color text boxes are adorned with the error template when one of them is updated. So, why not always raise the event in this manner? It\u2019s largely a matter of performance. It\u2019s possible that refreshing every property on an object could hamper performance. Of course, there\u2019s no way to know without testing, and your mileage may (and probably will) vary.<br \/>\nThe other solution is to raise the PropertyChanged event for the other dependent field(s) when one changes. The downside to using this mechanism is that you (or other developers who support your app) must know that the Make and Color properties are related through the validation code.<\/p>\n<p>INotifyDataErrorInfo<br \/>\nThe INotifyDataErrorInfo interface introduced in .NET 4.5 builds on the IDataErrorInfo interface and adds additional capabilities for validation. Of course, with additional power comes additional work! In a drastic shift from prior validation techniques that you had to specifically opt into, the ValidatesOnNotifyDataErrors binding property defaults to true, so adding the property to your binding statements is optional.<br \/>\nThe INotifyDataErrorInfo interface is extremely small but does take a fair amount of plumbing code to make it effective, as you will see shortly. The interface is shown here:<\/p>\n<p>public interface INotifyDataErrorInfo<br \/>\n{<br \/>\nbool HasErrors { get; }<br \/>\nevent EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;<br \/>\nIEnumerable GetErrors(string propertyName);<br \/>\n}<\/p>\n<p>The HasErrors property is used by the binding engine to determine whether there are any errors on any of the instance\u2019s properties. If the GetErrors() method is called with a null or empty string for the propertyName parameter, it returns all errors that exist in the instance. If a propertyName is passed into the method, only<br \/>\nthe errors for that particular property are returned. The ErrorsChanged event (like the PropertyChanged and<br \/>\nCollectionChanged events) notifies the binding engine to update the UI for the current list of errors.<\/p>\n<p>Implement the Supporting Code<br \/>\nWhen implementing INotifyDataErrorInfo, most of the code is usually pushed into a base model class, so it needs be written only once. Start by replacing IDataErrorInfo with INotifyDataErrorInfo in the CarPartial.cs class and add the interface members (you can leave the code from IDataErrorInfo in the class; you will be updating this later).<\/p>\n<p>public partial class Car: INotifyDataErrorInfo, IDataErrorInfo<br \/>\n{<br \/>\n...<br \/>\npublic IEnumerable GetErrors(string propertyName)<br \/>\n{<br \/>\nthrow new NotImplementedException();<br \/>\n}<\/p>\n<p>public bool HasErrors { get; } public event<br \/>\nEventHandler<DataErrorsChangedEventArgs> ErrorsChanged;<br \/>\n}<\/p>\n<p>Next, add a Dictionary&lt;string,List<string>&gt; that will hold any errors grouped by property name, as shown here:<\/p>\n<p>private readonly Dictionary&lt;string,List<string>&gt; _errors<br \/>\n= new Dictionary&lt;string, List<string>&gt;();<\/p>\n<p>The HasErrors property should return true if there are any errors in the dictionary. This is easily accomplished like this:<\/p>\n<p>public bool HasErrors =&gt; _errors.Any();<\/p>\n<p>Next, create a helper method to raise the ErrorsChanged event (just like raising the PropertyChanged<br \/>\nevent) like this:<\/p>\n<p>private void OnErrorsChanged(string propertyName)<br \/>\n{<br \/>\nErrorsChanged?.Invoke(this,<br \/>\nnew DataErrorsChangedEventArgs(propertyName));<br \/>\n}<\/p>\n<p>As mentioned earlier, the GetErrors() method should return any and all errors in the dictionary if the parameter is empty or null. If a propertyName value is passed in, it will return any errors found for that property. If the parameter doesn\u2019t match (or there aren\u2019t any errors for a property), then the method will return null.<\/p>\n<p>public IEnumerable GetErrors(string propertyName)<br \/>\n{<br \/>\nif (string.IsNullOrEmpty(propertyName))<br \/>\n{<br \/>\nreturn _errors.Values;<br \/>\n}<br \/>\nreturn _errors.ContainsKey(propertyName)<br \/>\n? _errors[propertyName]<br \/>\n: null;<br \/>\n}<\/p>\n<p>The final set of helpers will add one or more errors for a property or clear all of the errors for a property (or all properties). Any time the dictionary changes, remember to call the OnErrorsChanged() helper method.<\/p>\n<p>private void AddError(string propertyName, string error)<br \/>\n{<br \/>\nAddErrors(propertyName, new List<string> { error });<br \/>\n}<br \/>\nprivate void AddErrors(<br \/>\nstring propertyName, IList<string> errors)<\/p>\n<p>{<br \/>\nif (errors == null || !errors.Any())<br \/>\n{<br \/>\nreturn;<br \/>\n}<br \/>\nvar changed = false;<br \/>\nif (!_errors.ContainsKey(propertyName))<br \/>\n{<br \/>\n_errors.Add(propertyName, new List<string>()); changed = true;<br \/>\n}<br \/>\nforeach (var err in errors)<br \/>\n{<br \/>\nif (_errors[propertyName].Contains(err)) continue;<br \/>\n_errors[propertyName].Add(err); changed = true;<br \/>\n}<br \/>\nif (changed)<br \/>\n{<br \/>\nOnErrorsChanged(propertyName);<br \/>\n}<br \/>\n}<br \/>\nprotected void ClearErrors(string propertyName = &quot;&quot;)<br \/>\n{<br \/>\nif (string.IsNullOrEmpty(propertyName))<br \/>\n{<br \/>\n_errors.Clear();<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\n_errors.Remove(propertyName);<br \/>\n}<br \/>\nOnErrorsChanged(propertyName);<br \/>\n}<\/p>\n<p>Now the question is \u201chow is this code activated?\u201d The binding engine listens for the ErrorsChanged<br \/>\nevent and will update the UI if there is a change in the errors collection for a binding statement. But the validation code still needs a trigger to execute. There are two mechanisms for this, and they will be discussed next.<\/p>\n<p>Use INotifyDataErrorInfo for Validations<br \/>\nOne place to check for errors is in the property setters, like the following example, simplified to just check for the ModelT validation:<\/p>\n<p>public string Make<br \/>\n{<br \/>\nget { return _make; } set<br \/>\n{<br \/>\nif (value == _make) return;<\/p>\n<p>_make = value;<br \/>\nif (Make == &quot;ModelT&quot;)<br \/>\n{<br \/>\nAddError(nameof(Make), &quot;Too Old&quot;);<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\nClearErrors(nameof(Make));<br \/>\n}<br \/>\nOnPropertyChanged(nameof(Make)); OnPropertyChanged(nameof(Color));<br \/>\n}<br \/>\n}<\/p>\n<p>The main issue with this approach is you have to combine validation logic with property setters, making the code harder to read and support.<\/p>\n<p>Combine IDataErrorInfo with INotifyDataErrorInfo for Validations<br \/>\nYou saw in the previous section that IDataErrorInfo can be added to a partial class, which means you don\u2019t have to update your setters. You also saw that the indexer automatically gets called when PropertyChanged is raised on a property. Combining IDataErrorInfo and INotifyDataErrorInfo provides you with the additional features for validations from INotifyDataErrorInfo and with the separation from the setters provided by IDataErrorInfo.<br \/>\nThe purpose of using IDataErrorInfo is not to run validations but to make sure your validation code that leverages INotifyDataErrorInfo gets called every time PropertyChanged is raised on your object. Since you aren\u2019t using IDataErrorInfo for validation, always return string.Empty from the indexer. Update the indexer and the CheckMakeAndColor() helper method to the following code:<\/p>\n<p>public string this[string columnName]<br \/>\n{<br \/>\nget<br \/>\n{<br \/>\nClearErrors(columnName); switch (columnName)<br \/>\n{<br \/>\ncase nameof(Id): break;<br \/>\ncase nameof(Make): CheckMakeAndColor(); if (Make == &quot;ModelT&quot;)<br \/>\n{<br \/>\nAddError(nameof(Make), &quot;Too Old&quot;); hasError = true;<br \/>\n}<br \/>\nbreak;<br \/>\ncase nameof(Color): CheckMakeAndColor(); break;<br \/>\ncase nameof(PetName):<\/p>\n<p>break;<br \/>\n}<br \/>\nreturn string.Empty;<br \/>\n}<br \/>\n}<br \/>\ninternal bool CheckMakeAndColor()<br \/>\n{<br \/>\nif (Make == &quot;Chevy&quot; &amp;&amp; Color == &quot;Pink&quot;)<br \/>\n{<br \/>\nAddError(nameof(Make), $&quot;{Make}'s don't come in {Color}&quot;); AddError(nameof(Color),<br \/>\n$&quot;{Make}'s don't come in {Color}&quot;); return true;<br \/>\n}<br \/>\nreturn false;<br \/>\n}<\/p>\n<p>Run the app, select Chevy, and change the color to Pink. In addition to the red adorners around the Make and Model text boxes, you will also see a red box adorner around the entire grid that holds the Car details fields (shown in Figure 29-3).<\/p>\n<p>Figure 29-3. The updated error adorner<\/p>\n<p>This is another advantage of using INotifyDataErrorInfo. In addition to the controls in error, the control defining the data context also gets adorned with the error template.<\/p>\n<p>Show All Errors<br \/>\nThe Errors property on the Validation class returns all the validation errors on a particular object in the form of ValidationError objects. Each ValidationError object has an ErrorContent property that contains the list of error messages for the property. This means the error messages you want to display are in this list within a list. To display them properly, you need to create a ListBox that holds a ListBox to display the data. It sounds a bit recursive, but it will make sense once you see it.<br \/>\nStart by adding another row to the DetailsGrid and make sure the Height of the Window is at least 300. Add a ListBox in the last row, and bind the ItemsSource to the DetailsGrid, using Validation.Errors for the path, as follows:<\/p>\n<p><ListBox Grid.Row=\"6\" Grid.Column=\"0\" Grid.ColumnSpan=\"2\" ItemsSource=\"{Binding ElementName=DetailsGrid, Path=(Validation.Errors)}\"><br \/>\n<\/ListBox><\/p>\n<p>Add a DataTemplate to the ListBox, and in the DataTemplate, add a ListBox that is bound to the ErrorContent property. The data context for each ListBoxItem in this case is a ValidationError object, so you don\u2019t need to set the data context, just the path. Set the binding path to ErrorContent, like this:<\/p>\n<p><ListBox.ItemTemplate><br \/>\n<DataTemplate><br \/>\n<ListBox ItemsSource=\"{Binding Path=ErrorContent}\"\/><br \/>\n<\/DataTemplate><br \/>\n<\/ListBox.ItemTemplate><\/p>\n<p>Run the app, select Chevy, and set the color to Pink. You will see the errors displayed in Figure 29-4.<\/p>\n<p>Figure 29-4. Showing the errors collection<\/p>\n<p>This just scratches the surface of what you can do with validations and with displaying the errors generated, but it should have you well on your way to developing informative UIs that improve the user experience.<\/p>\n<p>Move the Support Code to a Base Class<br \/>\nAs you probably noticed, there is a lot of code now in the CarPartial.cs class. Since this example has only one model class, this isn\u2019t terrible. But, as you add models to a real application, you don\u2019t want to have to add all of that plumbing into each partial class for your models. The best thing to do is to push all of that supporting code down to a base class. You will do that now.<br \/>\nAdd a new class file to the Models folder named BaseEntity.cs. Add using statements for System. Collections and System.ComponentModel. Make the class public, and add the INotifyDataErrorInfo interface, like this:<\/p>\n<p>using System;<br \/>\nusing System.Collections;<br \/>\nusing System.Collections.Generic; using System.ComponentModel; using System.Linq;<\/p>\n<p>namespace Validations.Models<br \/>\n{<br \/>\npublic class BaseEntity : INotifyDataErrorInfo<br \/>\n}<\/p>\n<p>Move all of the code from CarPartial.cs that relates to INofityDataErrorInfo into the new base class.<br \/>\nAny private methods and variables need to be made protected. Next, remove the INotifyDataErrorInfo<br \/>\ninterface from the CarPartial.cs class, and add BaseEntity as a base class, as follows:<\/p>\n<p>public partial class Car : BaseEntity, IDataErrorInfo<br \/>\n{<br \/>\n\/\/removed for brevity<br \/>\n}<\/p>\n<p>Now, any additional model classes you create will inherit all of the INotifyDataErrorInfo plumbing code.<\/p>\n<p>Leverage Data Annotations with WPF<br \/>\nWPF can leverage data annotations as well for UI validation. Let\u2019s add some data annotations to the Car model.<\/p>\n<p>Add Data Annotations to the Model<br \/>\nOpen Car.cs and add a using statement for System.ComponentModel.DataAnnotations. Add the [Required] and [StringLength(50)] attributes to Make, Color, and PetName. The Required attribute adds a validation rule that the property must not be null (admittedly, this is redundant for the Id property since it<br \/>\nis not a nullable int). The StringLength(50) attribute adds a validation rule that the value of the property cannot be longer than 50 characters.<\/p>\n<p>Check for Data Annotation\u2013Based Validation Errors<br \/>\nIn WPF you have to programmatically check for data annotation\u2013based validation errors. Two key classes for annotation-based validations are the ValidationContext and Validator classes. The ValidationContext class provides a context for checking a class for validation errors. The Validator class allows you to check an object for attribute-based errors within a ValidationContext.<br \/>\nOpen BaseEntity.cs, and add the following using statements:<\/p>\n<p>using System.ComponentModel;<br \/>\nusing System.ComponentModel.DataAnnotations;<\/p>\n<p>Next, create a new method named GetErrorsFromAnnotations(). This method is generic, takes a string property name and a value of type T as the parameters, and returns a string array. Make sure the method is marked as protected. The signature is listed here:<\/p>\n<p>protected string[] GetErrorsFromAnnotations<T>( string propertyName, T value)<br \/>\n{}<\/p>\n<p>In the method, create a List<ValidationResult> variable that will hold the results of validation checks and create a ValidationContext scoped to the property name passed into the method. When you have those two items in place, call Validate.TryValidateProperty, which returns a bool. If everything passes (in regard to data annotation validations), it returns true. If not, it returns false and populates the List<ValidationResult> with the errors. The complete code is shown here:<\/p>\n<p>protected string[] GetErrorsFromAnnotations<T>(<\/p>\n<p>string propertyName, T value)<br \/>\n{<br \/>\nvar results = new List<ValidationResult>();<br \/>\nvar vc = new ValidationContext(this, null, null)<br \/>\n{ MemberName = propertyName };<br \/>\nvar isValid = Validator.TryValidateProperty( value, vc, results);<br \/>\nreturn (isValid)<br \/>\n? null<br \/>\n: Array.ConvertAll(<br \/>\nresults.ToArray(), o => o.ErrorMessage);<br \/>\n}<\/p>\n<p>Now you can update the indexer method in CarPartial.cs to check for any errors based on data annotations. If any errors are found, add them to the errors collection supporting INotifyDataErrorInfo. This enables us to clean up the error handling. In the start of the indexer method, clear the errors for the column.<br \/>\nThen process the validations and finally the custom logic for the entity. The updated indexer code is shown here:<\/p>\n<p>public string this[string columnName]<br \/>\n{<br \/>\nget<br \/>\n{<br \/>\nClearErrors(columnName); var errorsFromAnnotations =<br \/>\nGetErrorsFromAnnotations(columnName, typeof(Car)<br \/>\n.GetProperty(columnName)?.GetValue(this,null)); if (errorsFromAnnotations != null)<br \/>\n{<br \/>\nAddErrors(columnName, errorsFromAnnotations);<br \/>\n}<br \/>\nswitch (columnName)<br \/>\n{<br \/>\ncase nameof(Id): break;<br \/>\ncase nameof(Make): CheckMakeAndColor(); if (Make == \"ModelT\")<br \/>\n{<br \/>\nAddError(nameof(Make), \"Too Old\");<br \/>\n}<br \/>\nbreak;<br \/>\ncase nameof(Color): CheckMakeAndColor(); break;<br \/>\ncase nameof(PetName): break;<br \/>\n}<br \/>\nreturn string.Empty;<br \/>\n}<br \/>\n}<\/p>\n<p>Run the app, select one of the vehicles, and add text for the color that is longer than 50 characters. When you cross the 50-character threshold, the StringLength data annotation creates a validation error, and it is reported to the user, as shown in Figure 29-5.<\/p>\n<p>Figure 29-5. Validating the required data annotation<\/p>\n<p>Customizing the ErrorTemplate<br \/>\nThe final topic is to create a style that will be applied when a control is in error and also update the ErrorTemplate to display more meaningful error information. As you learned in Chapter 27, controls are customizable through styles and control templates.<br \/>\nStart by adding a new style in the Windows.Resources section of MainWindow.xaml with a target type of TextBox. Next, add a trigger on the style that sets properties when the Validation.HasError property is set to true. The properties and the values to set are Background (Pink), Foreground (Black), and Tooltip to the ErrorContent. The Background and Foreground setters are nothing new, but the syntax for setting the ToolTip needs some explanation. The binding points back to the control that this style is applied to, in this case, the TextBox. The path is the first ErrorContent value of the Validation.Errors collection. The markup is as follows:<\/p>\n<p><Window.Resources><br \/>\n<Style TargetType=\"{x:Type TextBox}\"><br \/>\n<Style.Triggers><br \/>\n<Trigger Property=\"Validation.HasError\" Value=\"true\"><br \/>\n<Setter Property=\"Background\" Value=\"Pink\" \/><br \/>\n<Setter Property=\"Foreground\" Value=\"Black\" \/><br \/>\n<Setter Property=\"ToolTip\"\n\nValue=\"{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}\"\/><br \/>\n<\/Trigger><br \/>\n<\/Style.Triggers><br \/>\n<\/Style><br \/>\n<\/Window.Resources><\/p>\n<p>Run the app and create an error condition. The result will be similar to Figure 29-6, complete with a tooltip showing the error message.<\/p>\n<p>Figure 29-6. Showing a custom ErrorTemplate<\/p>\n<p>The previous style changed the appearance of any TextBox that has an error condition. Next, you will create a custom control template to update the ErrorTemplate of the Validation class to show a red exclamation mark and set the tooltips for the exclamation mark. The ErrorTemplate is an adorner, which<br \/>\nsits on top of the control. While the style just created updates the control itself, the ErrorTemplate will sit on top of the control.<br \/>\nPlace a setter immediately after the Style.Triggers closing tag within the style you just created. You will be creating a control template that consists of a TextBlock (to show the exclamation mark) and a BorderBrush to surround the TextBox that contains the error(s). There is a special tag in XAML for the control that is being adorned with the ErrorTemplate named AdornedElementPlaceholder. By adding a<br \/>\nname to this control, you can access the errors that are associated with the control. In this example, you want to access the Validation.Errors property so you can get the ErrorContent (just like you did in the Style. Trigger). Here is the full markup for the setter:<\/p>\n<p><Setter Property=\"Validation.ErrorTemplate\"><br \/>\n<Setter.Value><br \/>\n<ControlTemplate><br \/>\n<DockPanel LastChildFill=\"True\"><br \/>\n<TextBlock Foreground=\"Red\" FontSize=\"20\" Text=\"!\" ToolTip=\"{Binding ElementName=controlWithError, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}\"\/><br \/>\n<Border BorderBrush=\"Red\" BorderThickness=\"1\"><br \/>\n<AdornedElementPlaceholder Name=\"controlWithError\" \/><br \/>\n<\/Border><br \/>\n<\/DockPanel><br \/>\n<\/ControlTemplate><br \/>\n<\/Setter.Value><br \/>\n<\/Setter><\/p>\n<p>Run the app and create an error condition. The result will be similar to Figure 29-7.<\/p>\n<p>Figure 29-7. Showing a custom ErrorTemplate<\/p>\n<p>Wrapping Up Validations<br \/>\nThis completes your look at validation methods within WPF. Of course, there is much more that you can do. For more information, consult the WPF documentation.<\/p>\n<p>Creating Custom Commands<br \/>\nAs with the validations sections, you can continue working in the same project or create a new one and copy all of the code to it. I will create a new project named WpfCommands. If you are using the same project, be sure to pay attention to the namespaces in the code samples in this section and adjust them as needed.<br \/>\nAs you learned in Chapter 25, commands are an integral part of WPF. Commands can be hooked up to WPF controls (such as Button and MenuItem controls) to handle user events, such as the Click() event. Instead of creating an event handler directly and adding the code directly into the code-behind file, the Execute() method of the command is executed when the click event fires. The CanExecute() method is<br \/>\nused to enable or disable the control based on custom code. In addition to the built-in commands you used in Chapter 25, you can create your own custom commands by implementing the ICommand interface. By using commands instead of event handlers, you gain the benefit of encapsulating application code, as well as automatically enabling and disabling controls based on business logic.<\/p>\n<p>Implementing the ICommand Interface<br \/>\nAs a quick review from Chapter 25, the ICommand interface is listed here:<\/p>\n<p>public interface ICommand<br \/>\n{<br \/>\nevent EventHandler CanExecuteChanged; bool CanExecute(object parameter); void Execute(object parameter);<br \/>\n}<\/p>\n<p>Adding the ChangeColorCommand<br \/>\nThe event handlers for your Button controls will be replaced with commands, starting with the Change Color button. Start by adding a new folder (named Cmds) in your project. Add a new class named ChangeColorCommand.cs. Make the class public, and implement the ICommand interface. Add the following using statements (the first one might vary depending on whether you created a new project for this sample):<\/p>\n<p>using WpfCommands.Models; using System.Windows.Input;<\/p>\n<p>Your class should look like this:<\/p>\n<p>public class ChangeColorCommand : ICommand<br \/>\n{<br \/>\npublic bool CanExecute(object parameter)<br \/>\n{<br \/>\nthrow new NotImplementedException();<br \/>\n}<br \/>\npublic void Execute(object parameter)<br \/>\n{<br \/>\nthrow new NotImplementedException();<br \/>\n}<br \/>\npublic event EventHandler CanExecuteChanged;<br \/>\n}<\/p>\n<p>If the CanExecute() method returns true, any bound controls will be enabled, and if it returns false, they will be disabled. If a control is enabled (because CanExecute() returns true) and clicked, the Execute() method will fire. The parameter passed into both of these methods comes from the UI based on the CommandParameter property set on binding statements. The CanExecuteChanged event ties into the binding and notification system to inform the UI that the result of the CanExecute() method has changed (much like the PropertyChanged event).<br \/>\nIn this example, the Change Color button should work only if the parameter is not null and of type Car.<br \/>\nUpdate the CanExecute() method to the following:<\/p>\n<p>public bool CanExecute(object parameter)<br \/>\n=> (parameter as Car) != null;<\/p>\n<p>The value for the Execute() method parameter is the same as for the CanExecute() method. Since the Execute() method can execute only if the object is of type Car, the argument must be cast to an Car type and have the color updated, as follows:<\/p>\n<p>public void Execute(object parameter)<br \/>\n{<br \/>\n((Car)parameter).Color=\"Pink\";<br \/>\n}<\/p>\n<p>Attaching the Command to the CommandManager<br \/>\nThe final update for the command class is to type the command into the command manager. The CanExecute() method fires when the Window first loads and then when the command manager instructs it to reexecute. Each command class has to opt in to the command manager. This is done by updating the code regarding the CanExecuteChanged event, as follows:<\/p>\n<p>public event EventHandler CanExecuteChanged<br \/>\n{<br \/>\nadd => CommandManager.RequerySuggested += value; remove => CommandManager.RequerySuggested -= value;<br \/>\n}<\/p>\n<p>Updating MainWindow.xaml.cs<br \/>\nThe next change is to create an instance of this class that the Button can access. For now, you will place this in the code-behind file for the MainWindow (later in this chapter, you will move this into a view model). Open MainWindow.xaml.cs and delete the Click event handler for the Change Color button. Add the following using statements to the top of the file (again, the namespace may vary based on whether you are still using the same project or you started a new one):<\/p>\n<p>using WpfCommands.Cmds; using System.Windows.Input;<\/p>\n<p>Next, add a public property named ChangeColorCmd of type ICommand with a backing field. In the expression body for the property, return the backing property (make sure to instantiate a new instance of the ChangeColorCommand if the backing field is null).<\/p>\n<p>private ICommand _changeColorCommand = null; public ICommand ChangeColorCmd<br \/>\n=> _changeColorCommand ??= new ChangeColorCommand());<\/p>\n<p>Updating MainWindow.xaml<br \/>\nAs you saw in Chapter 25, clickable controls in WPF (like Button controls) have a Command property that allows you to assign a command object to the control. Start by connecting your command instantiated in the code-behind to the btnChangeColor button. Since the property for the command is on the MainWindow class, you use the RelativeSourceMode binding syntax to get to the Window that contains the Button, as follows:<\/p>\n<p>Command=\"{Binding Path=ChangeColorCmd,<br \/>\nRelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}\"<\/p>\n<p>The Button still needs to send in a Car object as the parameter for the CanExecute() and Execute() methods. This is assigned through the CommandParameter property. You set this to the SelectedItem of the cboCars ComboBox, as follows:<\/p>\n<p>CommandParameter=\"{Binding ElementName=cboCars, Path=SelectedItem}\"<\/p>\n<p>The complete markup for the button is shown here:<\/p>\n<p><Button x:Name=\"btnChangeColor\" Content=\"Change Color\" Margin=\"5,0,5,0\" Padding=\"4, 2\" Command=\"{Binding Path=ChangeColorCmd,\nRelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}\" CommandParameter=\"{Binding ElementName=cboCars, Path=SelectedItem}\"\/><\/p>\n<p>Testing the Application<br \/>\nRun the application. You will see that the Change Color command is not enabled, as shown in Figure 29-8, since there isn\u2019t a vehicle selected.<\/p>\n<p>Figure 29-8. A window with nothing selected<\/p>\n<p>Now, select a vehicle; the button will become enabled, and clicking it will change the color, as expected!<\/p>\n<p>Creating the CommandBase Class<br \/>\nIf you continued with this pattern for AddCarCommand.cs, there would be code that would be repeated between the classes. This is a good sign that a base class can help. Create a new class in the Cmds folder named CommandBase.cs and add a using for the System.Windows.Input namespace. Set the class to public and implement the ICommand interface. Change the class and the Execute() and CanExecute() methods to abstract. Finally, add in the updated CanExecuteChanged event from the ChangeColorCommand class. The full implementation is listed here:<\/p>\n<p>using System;<br \/>\nusing System.Windows.Input;<\/p>\n<p>namespace WpfCommands.Cmds<br \/>\n{<br \/>\npublic abstract class CommandBase : ICommand<br \/>\n{<br \/>\npublic abstract bool CanExecute(object parameter); public abstract void Execute(object parameter); public event EventHandler CanExecuteChanged<br \/>\n{<br \/>\nadd => CommandManager.RequerySuggested += value; remove => CommandManager.RequerySuggested -= value;<br \/>\n}<br \/>\n}<br \/>\n}<\/p>\n<p>Adding the AddCarCommand Class<br \/>\nAdd a new class named AddCarCommand.cs to the Cmds folder. Make the class public and add CommandBase as the base class. Add the following using statements to the top of the file:<\/p>\n<p>using System.Collections.ObjectModel; using System.Linq;<br \/>\nusing WpfCommands.Models;<\/p>\n<p>The parameter is expected to be an ObservableCollection<Car>, so check to make sure of this in the CanExecute() method. If it is, then the Execute() method should add an additional car, just like the Click event handler.<\/p>\n<p>public class AddCarCommand :CommandBase<br \/>\n{<br \/>\npublic override bool CanExecute(object parameter)<br \/>\n=> parameter is ObservableCollection<Car>; public override void Execute(object parameter)<br \/>\n{<br \/>\nif (parameter is not ObservableCollection<Car> cars)<br \/>\n{<br \/>\nreturn;<br \/>\n}<br \/>\nvar maxCount = cars.Max(x => x.Id); cars.Add(new Car<br \/>\n{<br \/>\nId = ++maxCount, Color = \"Yellow\", Make = \"VW\", PetName = \"Birdie\"<br \/>\n});<br \/>\n}<br \/>\n}<\/p>\n<p>Updating MainWindow.xaml.cs<br \/>\nAdd a public property named AddCarCmd of type ICommand with a backing field. In the expression body for the property, return the backing property (make sure to instantiate a new instance of the AddCarCommand if the backing field is null).<\/p>\n<p>private ICommand _addCarCommand = null; public ICommand AddCarCmd<br \/>\n=> _addCarCommand ??= new AddCarCommand());<\/p>\n<p>Updating MainWindow.xaml<br \/>\nUpdate the XAML to remove the Click attribute and add the Command and CommandParameter attributes. The AddCarCommand will receive the list of cars from the cboCars combo box. The entire button\u2019s XAML is as follows:<\/p>\n<p><Button x:Name=\"btnAddCar\" Content=\"Add Car\" Margin=\"5,0,5,0\" Padding=\"4, 2\" Command=\"{Binding Path=AddCarCmd,\nRelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}\" CommandParameter=\"{Binding ElementName=cboCars, Path=ItemsSource}\"\/><\/p>\n<p>With this in place, you can now add cars and update the color of cars using reusable code contained in stand-alone classes.<\/p>\n<p>Updating ChangeColorCommand<br \/>\nThe final step is to update the ChangeColorCommand to inherit from CommandBase. Change ICommand to CommandBase, add the override keyword to both methods, and delete the CanExecuteChanged code. It\u2019s really that simple! The new code is listed here:<\/p>\n<p>public class ChangeColorCommand : CommandBase<br \/>\n{<br \/>\npublic override bool CanExecute(object parameter)<br \/>\n=> parameter is Car;<br \/>\npublic override void Execute(object parameter)<br \/>\n{<br \/>\n((Car)parameter).Color = \"Pink\";<br \/>\n}<br \/>\n}<\/p>\n<p>RelayCommands<br \/>\nAnother implementation of the command pattern in WPF is the RelayCommand. Instead of creating a new class for each command, this pattern uses delegates to implement the ICommand interface. It is a lightweight implementation, in that each command doesn\u2019t have its own class. RelayCommands are usually used when there isn\u2019t any reuse needed for the implementation of the command.<\/p>\n<p>Creating the Base RelayCommand<br \/>\nRelayCommands are typically implemented in two classes. The base RelayCommand class is used when there aren\u2019t any parameters needed for the CanExecute() and Execute() methods, and RelayCommand<T> is used when a parameter is required. You will start with the base RelayCommand class, which leverages the CommandBase class. Add a new class named RelayCommand.cs to the Cmds folder. Make the class public and add CommandBase as the base class. Add two class-level variables to hold the Execute() and CanExecute() delegates.<\/p>\n<p>private readonly Action _execute; private readonly Func<bool> _canExecute;<\/p>\n<p>Create three constructors. The first is the default constructor (needed by the RelayCommand<T>-derived class), the second is a constructor that takes an Action parameter, and the third is a constructor that takes an Action parameter and a Func parameter, as follows:<\/p>\n<p>public RelayCommand(){}<br \/>\npublic RelayCommand(Action execute) : this(execute, null) { } public RelayCommand(Action execute, Func<bool> canExecute)<br \/>\n{<br \/>\n_execute = execute<br \/>\n?? throw new ArgumentNullException(nameof(execute));<br \/>\n_canExecute = canExecute;<br \/>\n}<\/p>\n<p>Finally, implement the CanExecute() and Execute() overrides. CanExecute() returns true if the Func is null; or if it is not null, it executes and returns true. Execute() executes the Action parameter.<\/p>\n<p>public override bool CanExecute(object parameter)<br \/>\n=> _canExecute == null || _canExecute();<br \/>\npublic override void Execute(object parameter) { _execute(); }<\/p>\n<p>Creating RelayCommand<T><br \/>\nAdd a new class named RelayCommandT.cs to the Cmds folder. This class is almost a carbon copy of the base class, except that the delegates all take a parameter. Make the class public and generic, and add RelayCommand as the base class, as follows:<\/p>\n<p>public class RelayCommand<T> : RelayCommand<\/p>\n<p>Add two class-level variables to hold the Execute() and CanExecute() delegates:<\/p>\n<p>private readonly Action<T> _execute; private readonly Func<T, bool> _canExecute;<\/p>\n<p>Create two constructors. The first takes an Action<T> parameter, and the second takes an Action<T><br \/>\nparameter and a Func<T,bool> parameter, as follows:<\/p>\n<p>public RelayCommand(Action<T> execute):this(execute, null) {} public RelayCommand(<br \/>\nAction<T> execute, Func<T, bool> canExecute)<br \/>\n{<br \/>\n_execute = execute<br \/>\n?? throw new ArgumentNullException(nameof(execute));<br \/>\n_canExecute = canExecute;<br \/>\n}<\/p>\n<p>Finally, implement the CanExecute() and Execute() overrides. CanExecute() returns true if the Func is null; or, if it is not null, it executes and returns true. Execute() executes the Action parameter.<\/p>\n<p>public override bool CanExecute(object parameter)<br \/>\n=> _canExecute == null || _canExecute((T)parameter); public override void Execute(object parameter)<br \/>\n{ _execute((T)parameter); }<\/p>\n<p>Updating MainWindow.xaml.cs<br \/>\nWhen you use RelayCommands, all of the methods for the delegates need to be specified when a new command is constructed. This doesn\u2019t mean that the code needs to live in the code-behind (as is shown here); it just has to be accessible from the code-behind. It could live in another class (or even another assembly), providing the code encapsulation benefits of creating a custom command class.<br \/>\nAdd a new private variable of type RelayCommand<Car> and a public property named DeleteCarCmd, as shown here:<\/p>\n<p>private RelayCommand<Car> _deleteCarCommand = null; public RelayCommand<Car> DeleteCarCmd<br \/>\n=> _deleteCarCommand ??=<br \/>\nnew RelayCommand<Car>(DeleteCar,CanDeleteCar));<\/p>\n<p>The DeleteCar() and CanDeleteCar() methods must be created as well, as follows:<\/p>\n<p>private bool CanDeleteCar(Car car) => car != null; private void DeleteCar(Car car)<br \/>\n{<br \/>\n_cars.Remove(car);<br \/>\n}<\/p>\n<p>Notice the strong typing in the methods\u2014this is one of the benefits of using RelayCommand<T>.<\/p>\n<p>Adding and Implementing the Delete Car Button<br \/>\nThe final step to tie it all together is to add the button and assign the Command and CommandParameter<br \/>\nbindings. Add the following markup:<\/p>\n<p><Button x:Name=\"btnDeleteCar\" Content=\"Delete Car\" Margin=\"5,0,5,0\" Padding=\"4, 2\" Command=\"{Binding Path=DeleteCarCmd,\nRelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}\" CommandParameter=\"{Binding ElementName=cboCars, Path=SelectedItem}\"\/><\/p>\n<p>Now when you run the application, you can test that the Delete Car button is enabled only if a car is selected in the drop-down and that clicking the button does indeed delete the car from the Car list.<\/p>\n<p>Wrapping Up Commands<br \/>\nThis concludes your brief journey into WPF commands. By moving the event handling out of the code- behind file and into individual command classes, you gain the benefit of code encapsulating, reuse, and improved maintainability. If you don\u2019t need that much separation of concerns, you can use the lighter- weight RelayCommand implementation. The goal is to improve maintainability and code quality, so choose the method that works best for you.<\/p>\n<p>Migrate Code and Data to a View Model<br \/>\nAs in the \u201cWPF Validations\u201d section, you can continue working in the same project, or you can create a new one and copy all of the code over. I will create a new project named WpfViewModel. If you are using the same project, be sure to pay attention to the namespaces in the code samples in this section and adjust as needed.<br \/>\nCreate a new folder named ViewModels in your project, and add a new class named<br \/>\nMainWindowViewModel.cs into that folder. Add the following namespaces and make the class public:<\/p>\n<p>using System.Collections.Generic; using System.Collections.ObjectModel; using System.Windows.Input;<br \/>\nusing WpfViewModel.Cmds; using WpfViewModel.Models;<\/p>\n<p>\u25a0Note a popular convention is to name the view models after the window they support. I typically follow that convention and will do so in this chapter. however, like any pattern or convention, this isn\u2019t a rule, and you will find a wide range of opinions on this.<\/p>\n<p>Moving the MainWindow.xaml.cs Code<br \/>\nAlmost all the code from the code-behind file will be moved to the view model. At the end, there will only be a few lines, including the call to InitializeComponent() and the code for setting the data context for the window to the view model.<br \/>\nCreate a public property of type IList<Car> named Cars, like this:<\/p>\n<p>public IList<Car> Cars { get; } = new ObservableCollection<Car>();<\/p>\n<p>Create a default constructor and move all the Car creation code from the MainWindow.xaml.cs file, updating the list variable name. You can also delete the _cars variable from MainWindow.xaml.cs. Here is the view model constructor:<\/p>\n<p>public MainWindowViewModel()<br \/>\n{<br \/>\nCars.Add(<br \/>\nnew Car { Id = 1, Color = \"Blue\", Make = \"Chevy\", PetName = \"Kit\", IsChanged = false }); Cars.Add(<br \/>\nnew Car { Id = 2, Color = \"Red\", Make = \"Ford\", PetName = \"Red Rider\", IsChanged = false });<br \/>\n}<\/p>\n<p>Next, move all the command-related code from the window code-behind file to the view model, updating the _cars variable reference to Cars. Here is just the changed code:<\/p>\n<p>\/\/rest omitted for brevity private void DeleteCar(Car car)<br \/>\n{<br \/>\nCars.Remove(car);<br \/>\n}<\/p>\n<p>Updating the MainWindow Code and Markup<br \/>\nMost of the code has been removed from the MainWindow.xaml.cs file. Remove the line that assigns the<br \/>\nItemsSource for the combo box, leaving only the call to InitializeComponent. It should now look like this:<\/p>\n<p>public MainWindow()<br \/>\n{<br \/>\nInitializeComponent();<br \/>\n}<\/p>\n<p>Add the following using statement to the top of the file:<\/p>\n<p>using WpfViewModel.ViewModels;<\/p>\n<p>Next, create a strongly typed property to hold the instance of the view model.<\/p>\n<p>public MainWindowViewModel ViewModel { get; set; }<br \/>\n= new MainWindowViewModel();<\/p>\n<p>Finally, add a DataContext property to the window\u2019s declaration in XAML.<\/p>\n<p>DataContext=\"{Binding ViewModel, RelativeSource={RelativeSource Self}}\"<\/p>\n<p>Updating the Control Markup<br \/>\nNow that the DataContext for the Window is set to the view model, the XAML bindings for the controls need to be updated. Starting with the combo box, update the markup by adding an ItemsSource.<\/p>\n<p><ComboBox Name=\"cboCars\" Grid.Column=\"1\" DisplayMemberPath=\"PetName\" ItemsSource=\"{Binding Cars}\" \/><\/p>\n<p>This works because the data context for the Window is the MainWindowViewModel, and Cars is a public property on the view model. Recall that binding calls walk up the element tree until a data context is located. Next, you need to update the bindings for the Button controls. This is straightforward; since the bindings are already set to the window level, you just need to update the binding statement to start with the DataContext property, as follows:<\/p>\n<p><Button x:Name=\"btnAddCar\" Content=\"Add Car\" Margin=\"5,0,5,0\" Padding=\"4, 2\" Command=\"{Binding Path=DataContext.AddCarCmd,\nRelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}\"\n\nCommandParameter=\"{Binding ElementName=cboCars, Path=ItemsSource}\"\/><br \/>\n<Button x:Name=\"btnDeleteCar\" Content=\"Delete Car\" Margin=\"5,0,5,0\" Padding=\"4, 2\" Command=\"{Binding Path=DataContext.DeleteCarCmd,\nRelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}\" CommandParameter=\"{Binding ElementName=cboCars, Path=SelectedItem}\" \/><br \/>\n<Button x:Name=\"btnChangeColor\" Content=\"Change Color\" Margin=\"5,0,5,0\" Padding=\"4, 2\" Command=\"{Binding Path=DataContext.ChangeColorCmd,\nRelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}\" CommandParameter=\"{Binding ElementName=cboCars, Path=SelectedItem}\"\/><\/p>\n<p>Wrapping Up View Models<br \/>\nBelieve it or not, you have just completed your first MVVM WPF application. You might be thinking, \u201cThis isn\u2019t a real application. What about data? The data in this example is hard-coded.\u201d And you would be correct. It\u2019s not a real app; it\u2019s demoware. However, that is the beauty of the MVVM pattern. The view doesn\u2019t know anything about where the data is coming from; it\u2019s just binding to a property on the view model. You can swap out view model implementations, perhaps using a version with hard-coded data for testing and one that hits the database for production.<br \/>\nThere are a lot of additional points that could be discussed, including various open source frameworks, the View Model Locator pattern, and a host of differing opinions on how to best implement the pattern.<br \/>\nThat\u2019s the beauty of software design patterns\u2014there are usually many correct ways to implement it, and then you just need to find the best manner based on your business and technical requirements.<\/p>\n<p>Updating AutoLot.Dal for MVVM<br \/>\nIf you want to update AutoLot.Dal for MVVM, you will have to apply the changes that we did for the Car<br \/>\nclass to all of the entities in the AutoLot.Dal.Models project, including the BaseEntity.<\/p>\n<p>Summary<br \/>\nThis chapter examined the WPF topics that support the Model-View-ViewModel pattern. You started off learning how to tie model classes and collections into the notification system in the binding manager. You implemented INotifyPropertyChanged and used ObservableCollections classes to keep the UI in sync with the bound data.<br \/>\nNext, you added validation code to the model using IDataErrorInfo and INotifyDataErrorInfo and checked for data annotation errors. You then displayed any validation errors in the UI so the user would know what the problem is and how to fix it, and you created a style and custom control template to render errors in a meaningful way.<br \/>\nFinally, you put it all together by adding a view model, and you cleaned up the UI markup and code- behind file to increase separation of concerns.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>CHAPTER 29 WPF Notifications, Validations, Commands, and MVVM This chapter will conclude your investigation of the WPF programming model by covering the capabilities that support the Model-View-ViewModel (MVVM) pattern. The first section covers the Model-View- ViewModel pattern. Next, you learn about the WPF notification system and its implementation of the Observable pattern through observable models [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[22],"class_list":["post-356","post","type-post","status-publish","format-standard","hentry","category-csharp","tag-pro-csharp10-with-net6"],"_links":{"self":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/356","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=356"}],"version-history":[{"count":0,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/356\/revisions"}],"wp:attachment":[{"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=356"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=356"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=356"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}