Real-time Google Analytics with MVVM

by Geert 18. January 2012 21:13

Inside Catel, there are several secret gems. One of these gems is the possibility to audit everything that happens in the view models (property changes, events, commands, etc). This is very useful for logging, or in the case of this blog post, real-time tracking with Google Analytics.

Show me first

Below is a movie that demonstrates the example application with real-time tracking:

Cool, now show me the code

The code is pretty simple. First you need to create an implementation of the IAuditor interface. The prevent that you need to implement all methods, there is a convenience implementation in the form of the AuditorBase. For the Google Analytics implementation, we use Web-Analysis.net (also used in the Microsoft Silverlight Analytics Framework).

   1: /// <summary>
   2: /// Google Analytics auditor.
   3: /// </summary>
   4: public class GoogleAnalytics : AuditorBase
   5: {
   6:     private readonly ApplicationTracker _appTracker;
   7:  
   8:     public GoogleAnalytics(string apiKey, string applicationName)
   9:     {
  10:         Argument.IsNotNull("apiKey", apiKey);
  11:         Argument.IsNotNull("applicationName", applicationName);
  12:  
  13:         _appTracker = new ApplicationTracker(apiKey, applicationName);
  14:         _appTracker.StartSession();
  15:     }
  16:  
  17:     public override void OnCommandExecuted(IViewModel viewModel, string commandName, ICatelCommand command, object commandParameter)
  18:     {
  19:         _appTracker.TrackEvent(ApplicationTrackerCategories.Command, string.Format("{0}.{1}", viewModel.GetType().Name, commandName));
  20:     }
  21:  
  22:     public override void OnViewModelCreated(Type viewModelType)
  23:     {
  24:         _appTracker.TrackPageView(viewModelType.Name);
  25:  
  26:         _appTracker.TrackCustomEvent("ViewModel.Created", viewModelType.Name);
  27:     }
  28:  
  29:     public override void OnViewModelCanceled(IViewModel viewModel)
  30:     {
  31:         _appTracker.TrackCustomEvent("ViewModel.Canceled", viewModel.GetType().Name);
  32:     }
  33:  
  34:     public override void OnViewModelSaved(IViewModel viewModel)
  35:     {
  36:         _appTracker.TrackCustomEvent("ViewModel.Saved", viewModel.GetType().Name);
  37:     }
  38:  
  39:     public override void OnViewModelClosed(IViewModel viewModel)
  40:     {
  41:         _appTracker.TrackCustomEvent("ViewModel.Closed", viewModel.GetType().Name);
  42:     }
  43: }

Last but not least, you need to register the auditor in the AuditorManager.

   1: AuditingManager.RegisterAuditor(new GoogleAnalytics(myApiKey, "Catel Analytics Example"));

Easy huh, creating real-time Google Analytics for your app Glimlach. The advantages is that you can now see exactly what your users are doing and what features of your application are used most (and thus should have a higher priority for support calls).

Tags: ,

C# | MVVM

When you should stop using MVVM…

by Geert 17. January 2012 20:22

Who would even thought this post would come from me, but today I saw a tweet that made me very, very unhappy… It was something like this (don’t want to quote people by name, everyone has a right to an opinion):

“How nice, my view models are completely auto generated…”

Let me explain (or at least try to) why bothers me so much about this. MVVM is a good pattern, so good that I decided to write a framework for it (called Catel). I like it and use it in all my applications. Below are the reasons why I like MVVM:

  1. Testable view logic (because you do not use any UI elements in your VM)
  2. Separation of concerns
  3. Protection of your models
  4. It’s it the pattern of the century!

The last reason is nonsense, but it seems that everyone is just using MVVM because it is MVVM. The reason why you *should* be using MVVM is because you are writing logic of a view or to protect a model.

As soon as you see words as “auto-generated”, “automatic”, etc in a view model, it is WRONG. And why? Because you can bind directly to the model as well (because that is all an “auto-generated” VM can do), saves you a lot of performance. One on one bindings which create an additional layer called view model is not fancy and should be avoided at all cost.

So, think again why you have started using MVVM and keep asking yourself the following questions:

  1. Do I want to be able to unit test my view logic and am I actually doing that?
  2. Do I want a clean separation of concerns (and is it separated, or am I using DependencyObject or any other UI elements in my view model)?
  3. Do I want to protect my models by exposing only a set of the properties to a view?

If the answer to all those questions is no, stop using MVVM. Seriously, just code everything in your code behind, add dependency properties to your “view model” and do something like this:

   1: public MyView()
   2: {
   3:     InitializeComponent();
   4:  
   5:     DataContext = this;
   6: }

Tags:

MVVM

Catel: Hooking a command to validation automatically in MVVM

by Geert 20. December 2011 19:42

In Catel (2.5, not released yet, only beta available), it is possible to hook the CanExecute of a Command to the IValidationSummary automatically. This way, there is no need to check for errors manually in the CanExecute. The example below first adds a validation summary to a view model to get the validation result. Then, it uses this validation summary to automatically determine whether a command can be executed.

1. Add validation to a person view model (note how the validation adds the tag PersonValidation to a validation):

   1: /// <summary>
   2: /// Validates the field values of this object. Override this method to enable
   3: /// validation of field values.
   4: /// </summary>
   5: /// <param name="validationResults">The validation results, add additional results to this list.</param>
   6: protected override void ValidateFields(System.Collections.Generic.List<IFieldValidationResult> validationResults)
   7: {
   8:     if (string.IsNullOrEmpty(FirstName))
   9:     {
  10:         validationResults.Add(FieldValidationResult.CreateError(FirstNameProperty, "First name cannot be empty", "PersonValidation"));
  11:     }
  12:  
  13:     if (string.IsNullOrEmpty(LastName))
  14:     {
  15:         validationResults.Add(FieldValidationResult.CreateError(LastNameProperty, "Last name cannot be empty", "PersonValidation"));
  16:     }
  17: }

2. Add a property to the view model containing the validation summary using the ValidationToViewModel attribute.

   1: [ValidationToViewModel(Tag = "PersonValidation")]
   2: public IValidationSummary PersonValidationSummary { get; set; }

3. Define a command on the view model:

   1: /// <summary>
   2: /// Gets the Save command.
   3: /// </summary>
   4: public Command Save { get; private set; }
   5:  
   6: /// <summary>
   7: /// Method to invoke when the Save command is executed.
   8: /// </summary>
   9: private void OnSaveExecute()
  10: {
  11:     // TODO: Handle command logic here
  12: }

4. Create the command that automatically uses the validation summary using the CommandHelper class:

   1: Save = CommandHelper.CreateCommand(OnSaveExecute, () => PersonValidationSummary);

With this example, the Save command on the view model can only be executed when there are no errors with the PersonValidation tag.

Tags: ,

Catel | C# | MVVM | Silverlight | WPF | Windows Phone 7

Catel: improved validation and the ValidationContext

by Geert 2. December 2011 12:20

In every release of Catel, we try to improve a significant part of the code based on user requests. For release 2.4, it was the turn of the validation.

The validation in Catel is extremely flexible, and allows to use validation in the model (exposed via INotifyDataErrorInfo or IDataErrorInfo), validation in the view model (via the Validate methods) or via attributes (data annotations) on either the model or view model. However, this doesn’t seem enough for some users that require the absolute freedom in validation. Therefore, after intense discussions with the users, we came up with the following changes.

Introduction of IValidator and IValidatorProvider

The first request was to allow external validators to get involved into the validation process. For example, some use Fluent Validation for advanced validation checks. In previous versions of Catel, the calls to the external validators had to be implemented manually and converted to IValidationResult interfaces.

To make it much easier to hook into the validation process, the IValidatorProvider and IValidator were developed. The IValidatorProvider is a class that returns the right IValidator for a specific type. If no validator is available, it will return null. The ViewModelBase will automatically check the ServiceLocator whether an IValidatorProvider is available, and will then retrieve the IValidator for the current instance automatically.

The IValidator itself contains lots of methods, and allows to hook into the following events:

  • BeforeValidation
  • BeforeFieldValidation
  • FieldValidation
  • AfterFieldValidation
  • BeforeBusinessRuleValidation
  • BusinessRuleValidation
  • AfterBusinessRuleValidation
  • AfterValidation

For example, it can use Fluent Validation in the FieldValidation  and BusinessRuleValidation, and can translate the errors in AfterValidation.

Introduction of IValidationContext

Another nice improvement is the creation of the IValidationContext. It takes over the responsibility as validation container from the DataObjectBase. This way, the DataObjectBase becomes a bit less complicated and at the same time, the new container allows querying of all validations of a specific object in a very flexible way. Below are a few examples on how to query validations of a specific object:

First, the ValidationContext can be retrieved from a view model like this:

   1: var viewModel = new MyViewModel();
   2: var validationContext = viewModel.ValidationContext;

Get all field errors with a specific tag

   1: var fieldErrorsWithTag = validationContext.GetFieldErrors((object)"myTag");

Get all field validations of a specific property

   1: var fieldValidationResultsForProperty = validationContext.GetFieldValidationResults("MyProperty");

Get all business rule warnings

   1: var businessRuleWarnings = validationContext.GetBusinessRuleWarnings();

We hope to release Catel 2.4 this weekend (waiting on the last feedback), so you don’t have to wait long for these features Glimlach.

Tags: ,

Catel | C# | WPF | Silverlight | MVVM | Windows Phone 7

Behaviors in the spotlight: Focus

by Geert 18. November 2011 11:16

Catel contains lots of behaviors that are very useful. For more information about behaviors, see the documentation. However, this series of blog posts with “Behaviors in the spotlight” will put one behavior in the spotlights. All behaviors in Catel are compatible with WPF, Silverlight and Windows Phone 7.

Below is a screenshot of the example application that can be found at http://catelexamples.codeplex.com that contains an example of all behaviors.

image

This time, the Focus behavior is the one that is in the spotlights.

Setting the focus when the control loads

The easiest and default method is to set the focus when the associated control is loaded. In WPF, this is immediately when the control is focused. In Silverlight, there is a delay of 500 milliseconds by default, otherwise the focus is not set correctly.

   1: <ListBox ItemsSource="{Binding PersonCollection}" SelectedItem="{Binding SelectedPerson}">
   2:     <i:Interaction.Behaviors>
   3:         <catel:Focus />
   4:     </i:Interaction.Behaviors>
   5: </ListBox>

 

Setting the focus when a specific property has changed

It is possible to set the focus when a specific event occurs. For example, when the layout root gets a MouseEnter event, the focus must be set on a specific control. This can be done via the following code:

   1: <ListBox ItemsSource="{Binding PersonCollection}" SelectedItem="{Binding SelectedPerson}">
   2:     <i:Interaction.Behaviors>
   3:         <catel:Focus FocusMoment="Event" Source="{Binding ElementName=layoutRoot}" EventName="MouseEnter" />
   4:     </i:Interaction.Behaviors>
   5: </ListBox>

 

Setting the focus when a specific event has occurred

It is possible to set the focus when a specific property changes. For example, when a value is set, the focus must move on to a new control. This can be done via the following code:

   1: <ListBox ItemsSource="{Binding PersonCollection}" SelectedItem="{Binding SelectedPerson}">
   2:     <i:Interaction.Behaviors>
   3:         <catel:Focus FocusMoment="PropertyChanged" Source="{Binding }" PropertyName="MyProperty" />
   4:     </i:Interaction.Behaviors>
   5: </ListBox>

 

Demonstration video

This video demonstrates the different modes of the behavior.


Download the demo

You can download the demo here:

Behaviors demo.zip (598.50 kb) [Downloads: 58]

Tags: , ,

C# | Catel | MVVM | Silverlight | Windows Phone 7 | WPF

About the Author

Geert van Horrik is a independent freelance software developer since January 1st, 2007. Since then he was been working on several projects from C++ to C# (WPF, ASP.NET, etc). Currently he loves to write his software using WPF (or Silverlight if WPF isn't an option).

Lately, Geert is spending a lot of time on Catel, a free open-source MVVM Framework for WPF and Silverlight. Actually, it's more than "just" an MVVM Framework, it's a complete application library!