Catel is a brand new framework (or enterprise library, just use whatever you like) with data handling, diagnostics, logging, WPF controls, and an MVVM Framework. So, Catel is more than "just" another MVVM Framework or some nice Extension Methods that can be used. It's more like a library that you want to include in all the (WPF) applications you are going to develop in the near future.

Introduction

Welcome to part 5 of the article series about Catel. This article explains how to write a real-world application using Catel. If you haven’t read the previous article(s) of Catel yet, it is recommended that you do. They are numbered, so finding them shouldn’t be too hard.

The goal of this article is represented by the following picture:

Idea to application

O boy, did the title promise too much? I don't think so! This article will show you how to write an application using Catel. This article includes using Catel in the following fields:

Data handling

Models are written using DataObjectBase, and include validation to make sure no invalid families can be saved (how can a family be invalid, but that's another question for another time). The example also uses serialization out-of-the-box to load/save data from/to disk.

WPF controls

The application is built by using controls of the Catel library. It includes popup windows, controls, and error handling.

MVVM

The application uses the MVVM Framework that ships with Catel. In this application, the real power of the framework becomes visible. This example uses View Models, services, nested controls, validation, and more. Also, the strength of the combination of a View Model with an intelligent Model in the background will become visible in this article.

Unit testing

Unit tests are very important to improve the quality of a software. One of the strongest points of the MVVM pattern is that it can be excellently combined with unit testing, and in this article, we will see how.

Each part of this article explains what to do step by step, but will also explain what parts of Catel are used during the specific steps. Each step can be skipped if required (for example, if you are only interested in how View Models are created). This way, you can fully focus on the points of the framework that you need.

This article will implement the application using the MVVM pattern. If you don't know what the MVVM pattern is, or if you are not yet familiar yet, read this very short introduction to MVVM. It is also recommended that you read the other articles of Catel first, but if you are smart enough, you should be able to get a grip of the framework by only viewing this example application.

In this article, we will first start by creating the project in Visual Studio. Then, we will build the application up from scratch by beginning with the Models (the data objects themselves). After the Models, the View Models (how are we going to show the Models to the user) will be created. And, finally, we will create the Views which will be the UI that the user will actually see. In real-life, a designer would do the last step based on the ViewModel, if you are lucky enough to be on a project with a GUI designer.

This example does not include writing unit tests, since it's unfair to write a whole application in one hour including unit tests. But, the MVVM framework gives you the ability to write unit tests whenever you please. Also, since I am not a designer, I don't want to put too much time into the UI itself. Therefore, the app might look a little bit sluggish, but hey, aren't all real-life applications a little bit sluggish?

When using Catel, it is very important to use the provided code snippets. In the first place, it saves you a lot of time, but it also saves you from mistakes. I have seen too much developers copy/paste dependency properties and forgetting to change the owner of the property. This will lead to very strange and unpredictable errors, since you will only get an error if you hit both the controls that register the dependency property on the same owner twice. An advantage of Catel is that it automatically determines the owner, so the dependency property mistake will not be made when using Catel. Still, it is very important to use the code snippets to correctly implement the code that uses Catel.

2. Functional requirements

Like every project, we need to start with the functional requirements. The functional requirements for this article are to make a hip, but still functional, and not too complex application. This made us thinking: what is hip, and still fairly easy to build and understand. The answer is social media. Maybe you are thinking: no, not another social media application. However, you don’t have to use or buy this application, it’s for demo purposes only, so if you don’t like the concept, just use it as a learning point.

I have an HTC Desire phone with Android, and it has a friend stream widget. This is a very cool widget that keeps me up-to-date with both Twitter and Facebook. I want to use this application as a good example of how social media should be implemented. I don’t want it to be too functional, that would divert from the actual purpose of this article.

2.1. Content providers

To support several social media sites, a content provider must be created. We will create an interface (or base class) that every content provider for every social network needs to provide.

2.2. User interface

What follows now are a few sketches on how the UI should look in the end, but don’t blame me if I can’t make it look nice.

The messages should be sorted by date/time, newest on top.

3. Creating the project

We are really going to start from scratch. We are going to create the solution and the projects. In this part, the right project types are created, and the libraries are linked to the projects. The reason that these steps are included is to show the recommended way of including third party libraries into a solution, and keep the solution organized and clean.

3.1. Features handled

log4net (logging);

themes and styles.

3.2. Directory structure

It’s very important to be consistent in organizing your projects. During the years, I found a structure that I like very much, since it gives me (and all people using Open-Source software that I develop) a very clear overview of what’s included in the package. Below is a screenshot of the directory structure:

Design: Contains the designs for the project, such as logo files, icons, etc. I like to keep this together with a software project to make sure all are saved in the source code repository.

Doc: Contains the documentation for the project. This can be as simple as a readme.txt and history.txt, but can also include functional and technical designs.

Lib: It is a good practice to keep the libraries used inside a project in the same directory. This way, you can simply replace libraries with a newer version and update all your projects at once instead of messing with files everywhere.

Output: The output folder isn’t created by you. If you set the output directory for your projects correctly (“..\..\output\Release\” for Release builds, “..\..\output\Debug\” for Debug builds), Visual Studio or the compiler will create the directories. But it’s nice not have to dig into the bin directory of each project, but that all files are written to the same output directory.

Src: This contains the source code, thus the solution, project files, and the actual source files.

3.3. Creating projects

It is very important to create a project that is maintainable and testable. Therefore, we want to make sure that the application uses “Separation of Concerns” (SoC). In its own way, MVVM is also an implementation of SoC, namely by dividing the UI, UI logic, and business logic from each other.

For this project to follow the rules of SoC, we need to create the following projects structure. It’s split up into separate folders because I like to keep things simple and clear. This may come in handy when projects become very large (think about 20 – 25 projects in one solution). First, let’s see how the projects structure looks like; after that, I can tell you more about the meaning of each project.

3.3.1. SocialMediaStream

This is the main application. It’s a WPF application (.NET 3.5 SP1), and is set as startup project, so it is started every time we are going to debug the application. This project includes the UI, but also the ViewModels since the ViewModels define the behavior of the UI.

This project will also be responsible to “couple” all behaviors together via Inversion of Control.

3.3.2. SocialMediaStream.Library

This .NET Class Library is the SDK of the application. Developers who want to write providers for the application will need this library. It contains the interface definitions and some “convenience” classes such as a base implementation of the ISocialMediaProvider interface.

3.3.3. SocialMediaStream.Providers.Facebook

This .NET Class Library is responsible for providing the Facebook implementation.

3.3.4. SocialMediaStream.Providers.Twitter

This .NET Class Library is responsible for providing the Twitter implementation.

3.3.5. SocialMediaStream.Test

This unit test project contains all the unit tests written for the application. Writing unit tests is out of the scope for this article, but since I needed them to make sure the app is somewhat stable, I thought including them would not harm anyone.

3.4. Enable logging

We want to be able to see what is actually happening, even after we deploy the software to all our clients. Therefore, logging is very important. Catel uses log4net, and even provides additional extension methods to make it easier to log exceptions and messages with formatting.

The use of log4net is very simple, and can be done via configuration. Below is an example configuration:

One of the nice things about Catel is that it is able to fix the margins of user controls. This way, you no longer have to worry about setting the margins for user controls to correct the spacing. The use of the StyleHelper class that is responsible for this behavior is very simple:

We will implement dynamic theme switching later in this article, since it is one of the last things to do.

4. Creating the Models

Creating the Models is important. In our case, we are going to create Models that are savable. In most business applications, an ORM mapper (like Entity Framework, NHibernate, LLBLGen Pro, etc.) is used, but including a database in our example is not required and will only distract from the core functionality of the software. A nice side-effect is that the DataObjectBase class (the most important class of all) is used for the Models, and therefore this example gives a good idea of what the class is capable of. However, I wanted to make sure to mention that Catel is fully compatible with any Model implementation as long as the Model implements the INotifyPropertyChanged interface, and if it doesn't, it shouldn't even be called a Model.

4.1. Features handled

DataObjectBase (Catel.Core);

Contracts via interfaces.

4.2. Interfaces

For the sake of Separation of Concerns (SoC), it is very important to create interfaces to define the contract between the different layers of the application.

4.2.1. ISocialMediaEntry

For the main application to be able to communicate with providers, there needs to be some sort of contract. This is normally done in the form of an interface so the objects can easily be mocked in unit tests. Below is the interface for a social media entry:

4.2.2. ISocialMediaProvider

Now that we have defined what information a social media entry can contain, it’s time to decide how to communicate with the providers. So let’s create an interface defining these properties and a method to get the updates from that specific provider:

We now have a contract between the main application and the providers that can be added as plug-ins. The only thing providers have to do is implement the ISocialMediaProvider interface, and it will be available for the application.

Since the providers of social media (at least the ones included in this article) use OAuth, there is no need to provide any username and/or password.

4.2.3. ISocialMediaProviderFactory

As I told you earlier in this article, it’s very important to separate your concerns. Therefore, we want to be able to create different factories that will find the social media providers. For example, in this application, we simply want to list all the assemblies in the current working directory and see if they contain any types that implement the SocialMediaProviderBase class. But imagine that you want to search for Web Services, a database, or something else. Therefore, we first need to define what the factory should do and create an interface for it:

Now that we have created an interface for the factory, we can create several implementations, and decide via configuration what factory to use. This allows us to change the factory from LocalSocialMediaProviderFactory to a WebServicesSocialMediaProvider or a DatabaseSocialMediaProvider.

4.3. Base provider

To simplify development for the providers, we will create a base class that will already implement the DataObjectBase class. This way, provider developers only have to implement the GetLast10Updates method and care about the actual connection with the social media they are responsible for. Thanks to the dataobject and dataproperty code snippets, the class below is created in just a few minutes' time:

4.4. Twitter and Facebook providers

I don’t want to dive too deep into the support for Twitter and Facebook, because this is not where the article is about. I did a quick search on Open-Source libraries for both providers and found these two:

Tweetsharp: TweetSharp is the most complete and most effective client library for communicating with Twitter. TweetSharp works how you want to: simple service, fluent interface, or LINQ provider. It's designed so that you write less, and get more, from Twitter's API.

If you are interested in how the libraries work, either check out the source code in this article or view the official websites for more information.

I must admit that I smuggled some with the time. Writing the Twitter and Facebook providers was a real pain in the ***. It was my first experience with OAuth, and both libraries I picked contained bugs that I walked into. You might call it destiny, I call it bad luck. Anyway, writing a whole app including the providers is not doable in one hour, but if there was a good SDK that came with good examples, it should be doable in theory. Still, writing this app without providers in an hour is extremely fast (I hope you still believe that now ).

4.5. SocialMediaProviderFactory

How do we determine what providers to use? We don’t want to create references to the Facebook and Twitter providers. We also want to make our application “future proof” so we don’t have to re-compile the application when a new provider is created. A great solution for this is the Factory pattern. This way, we create a single class responsible for finding and instantiating the providers.

For the sake of simplicity, this example application will only provide a factory that lists the assemblies inside the current working directory. The implementation is very simple, and should speak for itself:

5. Creating the View Models

Now that the Models are all set-up, it's time to think about the application and how the user should interact with the data (the Models). Since you need to be able to unit-test UI functionality, you need the logic to be testable without user interaction. The View Models are a great place to locate the logic of the View and determine what parts of the Models should be published to the UI (the View, and eventually the user), and how they should be published (should the user pick from a list, or is it text, or should specific fields be read-only?). The View Models are very easy to create, especially when the Model is correctly implemented.

5.1. Features handled

ViewModelBase (Catel.Windows).

5.2. SocialMediaEntryViewModel

There are several ways to divide code and UI. Some prefer using ItemTemplates for ItemsControls, I prefer creating a separate user control for these items. I have the following reasons to separate the UI (and its logic) into a separate control and ViewModel:

A separate user control for an item inside an ItemsControl control gives you the option to create separate View Models.

Soon or later, clients will request commands that should be executed on items inside an ItemsControl. This is very hard to accomplish, since the only way to know which item to execute the command for is by creating an additional Selectedxxx property or binding the command parameter via special mediator classes.

Sometimes, it’s just not possible to do everything inside the View Model containing the collection. For example, in our application, ISocialMediaEntry has a Photo property which is of the type System.Drawing.Bitmap. We can’t show this image directly in WPF, thus we need to convert it to a BitmapSource class. This isn’t and shouldn’t be the responsibility of the View Model containing the items, but the responsibility of the item itself.

Enough talk about the reasons why I decided to go for a separate item user control. Let’s go and see how it is implemented. The View Model looks very large, but thanks to the vm, vmprop, vmpropmodel, vmpropviewmodeltomodel, and vmpropcommandwithcanexecute code snippets, this class is created in just a few minutes:

This View Model consists of several parts. I will explain them one by one. Let’s start with the constructor. As you can see, there is only one constructor accepting an instance of ISocialMediaEntry. There is no way to fool the View Model by passing null, it will immediately throw an ArgumentNullException. The reason why there is only one constructor is the combination of UserControl<TViewModel> and the View Model. If the View Model only contains one constructor, UserControl<TViewModel> will automatically try to construct the View Model based on the current data context of the user controls. Sounds quite complex, but in practice, it isn’t. This control is going to be used inside an ItemsControl. The data context of each item is set to the item it represents (in our case, an instance of ISocialMediaEntry). As soon as the data context is set on the user control, it checks the attached View Model to see if it contains a constructor accepting the data context. If it does (and it does in our case), it will create the View Model and set it as the new data context.

Next, you see that we have a property declared with the Model attribute. It is the instance of the IsocialMediaEntry that is injected into the View Model via the constructor. Thanks to the Model attribute, it is possible to use the ViewModelToModel attribute.

All other properties, exception for Title and Photo, are decorated with the ViewModelToModel attribute. This is a convenience attribute so you don’t have to map the properties from/to the Model. In other words, when the property Url is decorated with the ViewModelToModel attribute, it tells the View Model to set the value of Url to the SocialMediaEntry.Url value as soon as the Model or the property on the Model changes. If you are creating an editable View Model, this attribute is also responsible for mapping changes from the UI back to the Model.

We also defined a command. It contains the CanExecute method (it’s only possible to open a link if there is a link) and the Execute method, which uses the IProcessService to start a new process for the URL. This results in the default browser opening the URL.

Last but not least, let’s take a closer look at the constructor again. As told earlier, as soon as the SocialMediaEntry property is set, all properties decorated with ViewModelToModel are automatically set. Since the Photo property of ISocialMediaEntry is of type System.Drawing.Bitmap, we need to convert it to a BitmapSource. Therefore, we don’t want to use automatic mappings, but we convert the Photo object ourselves via an Extension Method available in Catel.

5.3. MainWindowViewModel

We have discussed the most complex View Model of the application in the previous paragraph, if you can even call it complex. Let’s take a look at the View Model for the main window of the application. Again, we start with showing the code first, and then I will explain the code part by part.

Again, it might sound impossible, but this View Model is created within 10 minutes. The most complex was to implement the Initialize and Refresh methods, which required some actual coding. The rest of the view model is created using the vm, vmprop, and vmcommand code snippets.

Like in the previous chapter, let’s start with the constructor. Since this is the View Model, it does not require any special constructors. DataWindow<TViewModel> tries to construct the View Model using the empty constructor and sets it as the data context. However, in our example, we have two constructors, one with and one without arguments. The reason for this is explained a bit further in this article in the part Setting up IoC containers. So, until then, just assume there is a default constructor without arguments so the View Model can be constructed automatically.

Next, we have a collection of ISocialMediaEntry objects, which is obvious because we need to display a list of objects in our View. There are also two commands, one to visit the website of Catel, and one to refresh the social media manually.

This brings us to the most interesting part of the View Model for now: the use of the Factory and retrieving the updates of the social media. As explained earlier in this article, we really want our View Models to be testable and loosely coupled as possible. Therefore, we only use interfaces which allow us to do so. The View Model is injected with an instance of ISocialMediaProviderFactory so the View Model is able to retrieve a list of available ISocialMediaProvider instances. In the Initialize method, the View Model asks the user for each social media provider whether the user wants the application to support the specific provider. If so, it is stored in a special list containing all enabled social media providers.

Finally, we have a RefreshSocialMedia method that shows the PleaseWaitWindow via the IPleaseWaitService of the View Model. Then it retrieves all the updates for all enabled social media providers. Keep in mind that all of this is happening in the UI thread, so when an update takes a long time, that’s the reason. It’s better to use an asynchronous approach, but that would only increase the difficulty of our example application. I’ll leave implementing asynchronous updates up to the reader as a good exercise.

6. Creating the Views

The Views are the way the user experiences the application and is able to view and modify data. A View is, in an ideal situation, not created by a developer, but by a designer. However, there aren't much clients that actually want to spend money on designers (same for testers, even though they are very important!). I don't want to lose too much time on creating a very nice user interface, so the UI will be a bit basic. Even though the UI is basic, it's fully functional, and uses some controls and windows of Catel.

6.1. Features handled

DataWindow (Catel.Windows);

IoC containers;

UserControl (Catel.Windows);

TraceOutputWindow (Catel.Windows).

6.2. SocialMediaEntry

The user control consists of some simple XAML (notice that it derives from Catel.Windows.UserControl<TViewModel>instead of UserControl):

The interesting point is that this class also implements some kind of Interaction.Triggers. This is for the EventToCommand trigger to enable events to be converted to commands of a View Model. In this case, a MouseDoubleClick event will be converted to the OpenLink command of the View Model.

The XAML code is pretty straightforward. The only thing I want to mention is the use of the SocialMediaEntry control. As you can see, the ItemTemplate of the ListBox control defines an instance of the user controls and binds the DataContext property of the user control. This is very important so UserControl<TViewModel> will use that data context to instantiate the View Model discussed earlier.

The code-behind of the window is very clean, thanks to MVVM. It passes DataWindowMode.Custom to the base constructor to tell DataWindow<TViewModel> not to generate the default OK and Cancel buttons.

6.4. Setting up IoC containers

Now that we have prepared a very loosely coupled system, it’s time to couple the loose parts. Catel uses Unity to implement IoC containers. For now, there is just one thing we want to configure, and that is the ISocialMediaProviderFactory that should be used to collect the several providers.

First, we need to go to the app.config file and specify the section for the Unity configuration:

The Unity configuration section above tells Unity to create an instance of SocialMediaProviderFactory we created in the previous paragraph when ISocialMediaProviderFactory is requested from the container.

To make sure that Unity loads the configuration, we need to add this piece of code to the code-behind of the application (App.xaml.cs):

The code above configures the IoC configuration when the application starts up. The code that is executed should speak for itself.

We are almost there, hold on. We have set up the Factory interface, an example implementation, and configured the IoC container to instantiate the right class. The only thing left is to actually instantiate the Factory. We do this in the constructor of the main window View Model. We have created two constructors to be able to inject the factory to the main window View Model during unit tests (but of course, this can also be accomplished via configuring the IoC containers via the app.config of the unit test project):

///<summary>/// Initializes a new instance of the <seecref="MainWindowViewModel"/> class.
///</summary>///<remarks>/// This constructor is created to use an IoC container.
///</remarks>public MainWindowViewModel()
: this(Catel.IoC.UnityContainer.Instance.
Container.Resolve<ISocialMediaProviderFactory>()) { }
///<summary>/// Initializes a new instance of the <seecref="MainWindowViewModel"/> class.
///</summary>///<paramname="socialMediaProviderFactory">The social media provider factory.</param>///<remarks>/// This constructor is created to allow custom dependency injection.
///</remarks>public MainWindowViewModel(ISocialMediaProviderFactory socialMediaProviderFactory)
{
_socialMediaProviderFactor = socialMediaProviderFactory;
// Other code left out for sake of simplicity
}

The first constructor without any arguments uses the IoC container of Catel to resolve the configured implementation of ISocialMediaProviderFactory, which in our case will be SocialMediaProviderFactory.

6.5. TraceOutputWindow for additional debug info

The output window of Visual Studio is not visible at all times (we all want to see our own things), nor does it provide colored messages. Therefore, Catel comes with the TraceOutputWindow. The use of this window is very easy, and we are going to use it to show the log messages during debug sessions.

We want the TraceOutputWindow to show when the application is started, and it should be closed as soon as the user exits the application. What better place to use than the main window? Below is the additional code that we use to show the TraceOutputWindow during debug builds. First, we need to declare the window as a field:

Thanks to the #if and #endifdirectives, there will be no traces of this window during release builds.

6.6. Dynamic theme switching

I don’t want to keep the dynamic theme switching capabilities hidden from you, so let’s discuss this. It’s not too hard to understand, so it’s a nice finalizer for this article. Dynamic theme switching is implemented in the code-behind. The reason for this is that it has nothing to do with manipulating data, and we cannot unit test it properly without creating an Application object, nor can we see if it actually works. Therefore, it is perfectly legal to implement this behavior in the code-behind (because this is what the code-behind is for). If you are still not convinced why this is implemented in the code-behind, think of using the same View Model in Silverlight. Silverlight uses a different approach for theme handling, but the actual functionality works the same for Silverlight. This allows us to use exactly the same View Model for the main window in Silverlight, and the developers of the Silverlight version can decide for themselves whether they want to implement dynamic theme switching support.

There are several things we need to do to implement dynamic theme switching. Let’s start with the code-behind. We need a dependency property that defines both the available themes and the selected themes:

Now that we have implemented the logic that will take care of re-establishing the resource dictionaries of the application, let’s see how the collection of available themes is initialized. At the end of the constructor, we add this code:

Last but not least, we need to add controls on the main window to enable dynamic theme switching. After the row definitions of the first grid, we add this code:

<!-- Theme switching, not in view model because it has nothing to do with that --><WrapPanelOrientation="Horizontal"VerticalAlignment="Center"DataContext="{Binding RelativeSource=
{RelativeSource AncestorType={x:Type Windows:DataWindow}}}"><LabelContent="Theme"VerticalAlignment="Center"/><ComboBoxSelectedItem="{Binding SelectedTheme}"ItemsSource="{Binding AvailableThemes}"DisplayMemberPath="Name"VerticalAlignment="Center"/></WrapPanel>

As you can see, the DataContext of the WrapPanel is set to the DataWindow, not the View Model. Therefore, we can bind to the AvailableThemes and SelectedTheme dependency properties of the window.

7. Conclusion

I hope this article has shown you how powerful the Catel framework can be if used correctly. By combining data handling, validation, and WPF user controls, you are able to create applications extremely fast, and still be in full control of what happens.

This application did not include unit testing. This doesn’t mean that unit testing isn’t important at all. The reason unit testing is not included is because there already is a separate article all about unit testing. This article would become too big if all that stuff was handled in this article again.

Share

About the Author

I am Geert van Horrik, and I have studied Computer Science in the Netherlands.

I love to write software using .NET (especially the combination of WPF and C#). I am also the lead developer of Catel, an open-source application development framework for WPF, Silverlight, WP7 and WinRT with the focus on MVVM.

I have my own company since January 1st 2007, called CatenaLogic. This company develops commercial and non-commercial software.

Comments and Discussions

Congradulations on developing such a nice MVVM framework. Also congradulations on the excellent artical series you published on Catel.

And most importantly thanks for sharing all your effort and experiences with many other people like me.

After I started looking for a strong and yet clean and easy to use MVVM framework and some preliminary research I had the impression that either Cinch or Catel could be the best I could find.

Therefore first I've read all the Cinch series and the source code published by Sacha in this site. I thought Cinch is smart but still a bit hairy and not exactly straight to the point.

Then I've read all Catel series and the source code published you. My opinion is that you have really done it the way it should have been done. Very thorough, very straight to the point, very feature rich and yet still extremely clean design and implementation - hence well done again!!!

I have not used Catel framework yet but I plan to use it for many years and in many projects from now on.

One point that I really have concerns about Catel is this:

As I remember somewhere you say that the Model classes should also be derived from the DataObjectBase or they should at least provide INotifyPropertyChanged interface otherwise 2-way bindings will not be possible.

I like to use Catel for both WPF and Silverlight applications together with DB backends. So I like to use the generated Linq-To-Sql, Entity Framework or nHibernate classes as my models. And I don't want to introduce another layer of DTO objects. This is true for at least small/medium size projects which do not need serious service layer other than RIA Webservices provided out of box.

For instance since Ling-To-Sql classes are already derived from Entity class, we cannot derive them again from your DataObjectBase in a partial class. I believe that the ModelView classes, which are derived from your ViewModelBase, can deal with the Model classes, which are NOT derived from your DataObjectBase, so that an application based on Catel can happily work directly with the generated model classes such as EF or nHibernate classes.

On the other hand your recommended usage for DataObjectBase and ViewModelBase classes, [Model], [ViewModel], [ViewModelToModel] attributes suggest that under Catel we must create our own Model classes based on DataObjectBase even if this would mean we have to duplicate a lot of code that is generated by Linq-To-Sql, etc modules.

First of all, thanks for your kind words. It's always nice to see that after all these efforts, people actually see the power of the software

You can stop having concerns. The DataObjectBase is not necessary at all. Actually, it's just an example how a model can easily be created without actually requiring a database back-end. Requiring a database back-end is hard for demo applications, or if you simply want to store data in a file on a client. However, the model can be of ANY type.

The attributes to communicate with the model are "ease-of-use" attributes. They are not actually necessary, you can also copy all values from the model in the Initialize, and then write them back to the model in the Save method of the view model. Therefore, it is not necessary for the model to implement either INotifyPropertyChanged, IDataErrorInfo, etc. However, if you want real-time updates, it is best to implement the INotifyPropertyChanged (because the attributes use that interface to know that a model has changed). If you don't implement the interface in the model, the values are only initially read and written back to the model on changes in the view model.

We have experience in using objects from DataObjectBase, Entity Framework, Linq-to-Sql, LLBLGen Pro as model objects which could easily communicate with the view model. Therefore, the only requirement of the model is that it has properties that can be read/set. The rest is just luxury (for example, change notification, errors (so you don't have to define the same errors in the view model again), etc).

I hope this answers your questions and takes away your concerns. If you have any other questions, comments or feature requests, just let us know!

Thanks for your detailed response - and all my concerns faded away. By the way, even if Catel currently didn't support what I wanted, I was sure that it could easily do it with some minor changes here and there. This is because I believe, "and it is obvious", that the design and implementation of Catel is really very strong and impressive.

I'll start using it immediately and I don't think I will have any more concerns from now on. In the unlikely event that this will happen (somehow?) then for sure I'll ask you about it.

However I think my future messages will all be along the lines that "how I am happy using Catel's this feature, that feature, etc...".

Actually I guess some file is missing from the zip package since I first downloaded the source code and built it and ran it. It crashed at startup. So I downloaded the binary files, still crashed at startup.

I have an updated source code package. Removed dead reference to Facebook.Web.dll and Facebook.Web.Mvc.dll and change configuration to x86. I can send it to you if you like so it can save you a one minute or two.

Yes, actually I've decided to use Catel in my next project after I read your first articles of this Catel series. The reason? I'm lazy and I hate tedious work. Seems you do, too. So. Anyway, it's the MVVM framework I'm going to use going forward.

Finally figured it out. It's because I used 'Any CPU' as the 'Platform target'. And maybe one or more libraries this sample using are x86 only. And my OS is Windows 7 x64, so a 'Can not load log4net.dll' exception happened. I encountered this issue before. Glad that I fixed it, finally.