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

A weak event listener for WPF, Silverlight and Windows Phone 7

by Geert 23. November 2011 20:28

A small note upfront: this blog post does not contain catchy images or videos, but it is truly worth reading! Try to hang in there, or if you don’t care about any memory leaks in your app, this is the time to leave.

You have probably heard about weak events before. This blog post is not about the issue of the cause of weak events, there are lots of articles about that. This article is about the solution to it. Shortly said, when you do this in every class (just for the sake of explaining the problem, don’t start thinking this code has no business value):

   1: var log = Log.Instance;
   2: log.LogReceived += OnLogReceived;

As you can see, the log is a singleton, so there is only one living instance of the Log class. It will probably live as long as the app itself. Now you might be thinking: what’s wrong with this code? Nothing, until the app starts growing and growing and your users start complaining about memory issues.

What happens here is that you subscribe to the LogReceived event of the Log class. This subscription contains 2 things:

  1. What class do I need to call (null for static, otherwise the instance of the class)
  2. What method do I need to call

So, in fact now the Log class knows about the instance of the class that just subscribed to it and holds a reference to it (how else can it deliver the event, if it doesn’t know the address). Thus, the classes that subscribe to the Log and that do no unsubscribe will never be collected by the garbage collection.

I truly hope you understand the issue. If not, I recommend to read this excellent article, it dives into the issue a bit better.

Previous attempts

Lots of people tried to solve the puzzle before. So I thought it would be pretty easy to find a class that could help me use weak events for WPF, Silverlight and Windows Phone 7. However, none of them actually worked or supported all the scenarios I had in mind. Below are a few articles I wrote before I started writing my own weak event handler:

The closest one is the first, which uses the Silverlight toolkit implementation and improved it. However, it requires the developer to use static event handlers. Say that again? Only static event handlers? 99 % of my handlers are not static! So, I started tweaking the solution until I found out I completely rewrote it.

The golden grail

So, I think I found the golden grail, just like the others before me. You might be thinking: oh no, not again. But just wait and see, and maybe I can convince you just in time to improve the memory management of your app!

We just found the golden grail!

You can find the full code attached at the bottom of this blog post (including unit tests!), but here are the most important parts.

Open instance delegates

The key feature behind this implementation of the weak event pattern is open instance delegates. You are probably wondering: what the hell are open instance delegates? Well, good question, and I will try to explain it. An open instance delegate is just as a regular delegate, it points to the method of a specific class, but the biggest difference is that it does not bind to a specific instance. This means that it can be described as: I know you live on that street (method), but I have not clue in which city (instance) that is. The instance can be specified later. The delegate for a regular event handler looks like this:

   1: public delegate void OpenInstanceHandler(TTarget @this, object sender, TEventArgs e);

The @this is nothing special, it allows us to use the this keyword so everyone knows that the target should be passed there. As you can see, it contains 3 parameters. The first one is the target (the city), the second and third parameters are the parameters of the regular event handler.

Weak references

The weak event listener creates an open instance delegate and stores both the source and target in a WeakReference class. As soon as one of these references are no longer valid, the class is unbound. The good side of this approach is that this weak event listener does not leak when the event never fires.

So, what can it handle?

The following use cases are supported:

  • Instance source (event) and instance target (handler)
  • Static source (event) and instance target (handler)
  • Instance source (event) and static target (handler)

So, actually it handles everything that can cause a memory leak via event subscriptions!

Quality assured!

Well, as far as I can guarantee the quality. I wrote the code with care and wrote several unit tests to make sure that all situations I could think of succeed:

image

So, what can’t it handle and what are the downsides?

This weak event listener follows the rules of the .NET framework. So, it cannot subscribe to private events. If you want private events, do your own hacking (the source is available, you only have to change the DefaultEventBindingFlags at the top of the class).

There are a few downsides about using a weak event listeners in general:

  • It’s notation is ugly, the “original” .NET way looks way better
  • You have to name the event by string, that sucks (if you know a better way, contact me!)
  • It can only handle events with a handler of EventHandler<TEventArgs>
  • You become a lazy developer not caring about subscriptions

Enough! Show me how to use it!

I like to distinguish event subscriptions into 4 categories, all described below.

Instance to instance
This is the situation where an instance target subscribes to an instance event. The events are unbound as soon as either the target or source are collected.

   1: var source = new EventSource();
   2: var listener = new EventListener();
   3:  
   4: var weakEventListener = WeakEventListener<EventListener, EventSource, EventArgs>.SubscribeToWeakEvent(listener, source, "PublicEvent", listener.OnPublicEvent);

Instance to static
This is the situation where a static target subscribes to an instance event. The events are unbound as soon as the source is collected.

   1: var source = new EventSource();
   2:  
   3: var weakEventListener = WeakEventListener<EventListener, EventSource, EventArgs>.SubscribeToWeakEvent(null, source, "PublicEvent", EventListener.OnEventStaticHandler);

Static to instance
This is the situation where an instance target subscribes to a static event. The events are unbound as soon as the target is collected.

   1: var listener = new EventListener();
   2:  
   3: var weakEventListener = WeakEventListener<EventListener, EventSource, EventArgs>.SubscribeToWeakEvent(listener, null, "StaticEvent", listener.OnPublicEvent);

Static to static
This is not supported because you shouldn’t be using a weak event listener here. Static events with static event handlers simply cannot cause memory leaks because both the source and the target have no instance. However, it might be possible that you subscribe to an event too many times and the event fires too many times. But again, no memory issues here.

Oh… one more thing

Please, promise me that when you use this class, you won’t scatter it all over the place. In fact, I truly believe the best way to prevent memory leaks is to know what you are doing and unsubscribe when you are not longer interested in an object.

Only when you have no idea about the lifetime of a specific object, I recommend to use weak events.

WeakEventListener.zip (14.49 kb) [Downloads: 68]

Tags:

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

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: 52]

Tags: , ,

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

Catel 2.4 sneak preview: authentication behavior

by Geert 2. November 2011 17:40

In Catel, there exists the IAuthenticationProvider class, which allows runtime authentication hooks to determine whether an ICommand can be executed or not. As of today, this IAuthenticationProvider has been extended with a new method called HasAccessToUIElement.

This method is used by the Authentication behavior, which can hide, collapse or disable UI elements based on the current user state. This is very handy when, for example, specific UI elements can only be accessed or edited by users in a specific role.

Creating a provider

It is important to create an authentication provider:

   1: /// <summary>
   2: /// Example implementation of the <see cref="AuthenticationProvider"/>. This class is not really implemented
   3: /// like it should, because it shouldn't be this easy to set the current role. However, for the sake of simplicity,
   4: /// this class has a simple property with the role of the user.
   5: /// </summary>
   6: public class AuthenticationProvider : IAuthenticationProvider
   7: {
   8:     /// <summary>
   9:     /// Gets or sets the role the user is currently in.
  10:     /// </summary>
  11:     /// <value>The role.</value>
  12:     public string Role { get; set; }
  13:  
  14:     public bool CanCommandBeExecuted(ICatelCommand command, object commandParameter)
  15:     {
  16:         return true;
  17:     }
  18:  
  19:     public bool HasAccessToUIElement(FrameworkElement element, object tag, object authenticationTag)
  20:     {
  21:         var authenticationTagAsString = authenticationTag as string;
  22:         if (authenticationTagAsString != null)
  23:         {
  24:             if (string.Compare(authenticationTagAsString, Role, true) == 0)
  25:             {
  26:                 return true;
  27:             }
  28:         }
  29:  
  30:         return false;
  31:     }
  32: }

Registering the provider

The authentication provider must be registered in the ServiceLocator of Catel:

   1: Catel.IoC.ServiceLocator.Instance.RegisterType<IAuthenticationProvider, AuthenticationProvider>();

Adding the behavior

Add the following namespaces to a xaml page:

   1: xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
   2: xmlns:catel="http://catel.codeplex.com"

Last but not least, it is time to add the behavior to a control. As you can see, it is possible to provide a custom AuthenticationTag, which is passed to the IAuthenticationProvider:

   1: <TextBox>
   2:     <i:Interaction.Behaviors>
   3:         <catel:Authentication AuthenticationTag="Administrator" Action="Disable" />
   4:     </i:Interaction.Behaviors>
   5: </TextBox>

Conclusion

Below are screenshots of the example applications (which can be found at http://catelexamples.codeplex.com or at the bottom of this post):

Logged in as administrator:

image

Logged in as read-only user:

image

Can I use this right away?

Yes! You can either download the demo application or the latest beta of Catel:

Do I need to use Catel all the way to use this behavior?

No, Catel is a toolkit, which means that you can use just the stuff you like. The only requirements are an implementation of the IAuthenticationProvider and it needs to be registered into the ServiceLocator (but no worries, the ServiceLocator supports MEF, Unity, Castle Windsor and Ninject).

Tags:

C# | Catel | MVVM | 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!