Additionally, if you haven't downloaded the modified Northwind database or the SharedAssemblies, you will need to download them at the bottom of the Lesson intropage. (Click me)
(Click on the link and the DB is at the bottom of the lesson.)
Please be sure to modify the app.config file to point to the machine you which you setup restore the database too.
All the assemblies used for the demo are contained in the SharedAssemblies folder so you may need to set your reference paths accordingly.
A big thanks to Sacha Barber for Cinch, Josh Smith for all his work and RelayCommand and the others who have taken the time to post helpful work on the internet.
My hope is this lesson doesn't get too large and validation isn't necessarily tied to a Model or MVVM for matter. The info about validation shows how you can utilize the validation capabilities of WPF while following MVVM patterns.
Sacha Barber has a DataWrapper class in his Cinch framework which I really like the capabilities it gives you with utilizing IDataErrorInfo . I really like the ability his class provides. Especially the ability to create your own validation rules.
What is a Model as it pertains to MVVM? The following is a definition from Wikipedia:
"Model: as in the classic MVC pattern, the model refers to the data access layer representing the real state content."
To me there is some confusion. Some people seem to use it to only mirror their database tables and fields. Some do this and also include their CRUD operations. For me I like for it to define only my data objects. I prefer to put all my BI, CRUD in a separate Service class. From what I see in the Prism samples, this is the way they choose to do this as well.
In our Lesson 4 sample, I created a NWDataProvider assembly for which I created a LinqToSql ORM. My data models for all my modules pretty much mirror the linq to SQL objects.
The reason I create my own data objects are for a couple of reasons. I like having the ability to separate the data models used in my application from the data provider should I ever want to change data providers. With my own data objects, really all I have to do is plug in a new ORM or whatever and make some mods my assemblers.
Next, as you will learn if you utilize the Cinch Framework, we can create our data models to cater to any features of the platform we're working with. In the case of WPF, using the DataWrapper, we can create the ability to change whether the controls that bind to a property are editable.
We can create Validation rules that automatically get enforced with any UI Element that binds to a property. Also we can track value changes and the ability to undo changes automatically to any UI Element which binds to one of our DataWrapper properties.
Instead of trying to rehash what Sacha has done a very nice job of explaining in his Cinch articles, I'm going to redirect you to where he has them posted. http://www.codeproject.com/KB/WPF/CinchIV.aspx
In Sacha's examples you'll see that all of his models override some of the methods from the EditableValidatingObject
I like to create a BaseModel object and place it in the infrastructure assembly and do all the overrides and create my CachedListOfDataWrappers property there so I don't have to duplicate code in all the models I create.
Next we move to the CustomerModel. I have macros which are attached below I use to generate all the code you see in this Model classes. (You'll note that I append Model t all my model objects. I don't think that is standard but it makes it easier I think for educational purposes.) All I have to do is type out my fields like so:
string companyName;
string contactName;
Then I highlight these and run CreateDataWrapperConstructor. It generates the code I need for my Model constructor. I copy this code, then I an undo. I then create the constructor and paste the contents in the constructor.
Next on the same fields, I run the CreatePropertiesDataWrapperNotifyPropertyChanged macro. This will generate everything else. One extra step you'll have to perform is when the changearg is created, I don't have access to the class name so I put a dummy string called PlaceHolder instead. So copy the Model's class name, in this case CustomerModel and do a replace on all Placeholder's in the document.
Upon creation it will look like this:
Code:
static PropertyChangedEventArgs _companyNameChangeArgs = ObservableHelper.CreateArgs<PlaceHolder>(x => x.CompanyName);
Code:
static PropertyChangedEventArgs _companyNameChangeArgs = ObservableHelper.CreateArgs<CustomerModel>(x => x.CompanyName);
Code:
<TextBox x:Name="TxtContactTitle" Margin="5" Text="{Binding Path=CurrentCustomerModel.ContactTitle.DataValue, Mode=TwoWay,
UpdateSourceTrigger=LostFocus, ValidatesOnDataErrors=True,
ValidatesOnExceptions=True}"
nsvmvvm:NumericTextBoxBehavior.IsEnabled="False"
Style="{StaticResource ValidatingTextBox}"
IsEnabled="{Binding Path=CurrentCustomerModel.ContactTitle.IsEditable}"
Grid.Row="0" Grid.Column="6" MaxLength="30"/>
DataWrapperHelper.SetMode(_cachedListOfDataWrappers, ViewMode.EditMode);
Then any UI Element such as a text box bound to on of the properites will be editable. Very nice I think.
The above statement I ran in a constructor of a Model object so anything that was bound to any of the was always editable.
In closing, I would like to clarify, you don't necessarily need to use DataWrapper in creating your Models. A Model as far as MVVM is concerned is just a way to persist data. However, as you will see with frameworks like Cinch, you can utilize quite a bit of WPF functionality when designing your models.
Again, I've seen some put BI & CRUD in their model. It seems that the Prism samples put the BI & CRUD etc in a Service class and is what I prefer.
DataWrapper adds a lot of nice functionality that is commonly needed in a WPF data object.
Again for more info on Cinch which contains DataWrapper and a lot more useful functionality, I recommend you visit Sacha Barber's space at codeproject.
The attached file CSharpMacros.Zip will extract out to a txt file. Open it and copy everything and open up the Macros IDE in Visual Studio and paste it into a module. There are other macros for creating things such as Properties can classes for use with WCF.







Section Widget
Categories Widget (top-down)


Rate this article