Invoking commands from events using the InvokeCommandAction behavior

MVVM is something for me. Databinding your data and behavior so you don’t have any code in your views is for me a nice separation of concepts. However some control’s cannot execute a command for certain events, for example when you select something in a listbox.

Enters InvokeCommandAction, which is a behavior which allows you to invoke a command when a certain event occurs. You can find it beneath Blend’s 4 behaviors:

image

You can attach this behavior to any control, and then select which command to execute when an event occurs. Let’s use a simple ListBox with strings example:

<Window
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:viewModels="clr-namespace:CommandsAndEvents"
       xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" x:Class="CommandsAndEvents.Window1"
       Title="Window1" Height="300" Width="300">
  <Window.DataContext>
    <viewModels:ListViewModel />
  </Window.DataContext>
    <Grid>
    <ListBox x:Name="listBox" ItemsSource="{Binding Names}" >
    </ListBox>
  </Grid
>
</
Window
>

This window will show a list of names from the following ListViewModel:

public class ListViewModel
{
 
public
ListViewModel()
  {
    Names =
new ObservableCollection<string> { "Jan", "Piet", "Joris", "Corneel"
};
    SelectionChangedCommand =
    
new RelayCommand("Test", (item) => ShowSelected((string
)item)); // string is the type of the selected item
  }

 
public ObservableCollection<string> Names { get; set
; }



 
public ICommand SelectionChangedCommand { get; set
; }


 
private void ShowSelected(string
item)
  {
   
MessageBox.Show(item);
  }
}

Now, if I’d like the ListBox to call the SelectionChangedCommand I simply add the following behavior:

<ListBox x:Name="listBox" ItemsSource="{Binding Names}" >
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
      <i:InvokeCommandAction Command="{Binding SelectionChangedCommand}"
 
                            
CommandParameter="{Binding SelectedItem, ElementName=listBox}"/>
    </i:EventTrigger>
  </i:Interaction.Triggers>
</ListBox>

 

Notice that this allows for arguments to be passed to the command, which then allows you access to any property on the control!

Entity Framework 4 with Self Tracking Entities - Splitting up the generated entities onto a shared Entities assembly with (almost) no fuss

I love the new Entity Framework 4 T4 templates for generating POCO’s and Self Tracking Entities. However the generated code ends up in a single assembly, mixing database independent POCO’s and STE’s with Entity Framework specific code. I like my entities to be in another project. How can we do this? This blog post is a walk-through on how to do this.

For this to work we need at least two library projects, one for the entities, and one for the data access layer.

In your data access layer project start by adding your Entity Framework (EF) model, either using database first or model first. In this walk-through I’ll be using database first, and using Northwind (gasp) as the database.

Add a new ADO.NET Entity Data Model to the DAL project, calling it NorthwindModel.edmx:

image

In the wizard choose “Generate from database”:

image

Follow through with the wizard, at the end selecting Categories and Products:

image

Update your model as you see fit…

The code being generated is the old EF3 kind of code, with classes deriving from EntityObject. I don’t want to use these classes as they couple my entities too much to EF. So instead I want to use Self Tracking Entities (of POCO’s). Next step is to right-click your model’s background and select Add Code Generation Item…

image

In this case you will be asked what code generation template you’d like to use. These template are actually T4 templates you can customize.

image

Choose the template of your liking, I’ll choose the ADO.NET Self-Tracking Entity generator using NorthwindModel.tt as the name. This will generate entities who will easily travel over borders using WCF. POCO’s lack the DataContract and DataMember support, but if you like, you can always add these to the T4 template yourself. More on this in a later post.

You should now end up with three files in your project:

image

The first contains EF specific code, so you should leave that one here. The second is the model, again EF specific. The third file, however, contains your entities and can be used without EF, so I’d like to move that to my entities project.

Unfortunately you cannot simply move the file over to the other project, because inside the NorthwindModel.tt T4 file there is a direct reference to the model:

string inputFile = @"NorthwindModel.edmx";

So we’ll need to use another technique. Right-click on your entities project and choose Add Existing Item…

Browse to your DAL project and search for the NorthwindModel.tt file (you’ll need to change the file filter in the dialog). Now you want to click on the little arrow on the add button  and select the Add As Link option. This option will leave the file in its original location where the model’s file reference can be found.

image

However, the generated code will now be part of your entities library. Before you compile  the entities project you’ll need to add a reference to System.Runtime.Serialization because the STE use the WCF’s DataContract attributes. Also, make sure the T4 code generation happens by right-clicking the NorthwindModel.tt file and selecting Run Custom Tool:

image

Now go back to the DAL project. We need to remove the code generation for the model in this project (since the code is now in the entities project). Right-click the NorthwindModel.tt file and select Exclude from Project:

image

Almost there.

The final problem will happen when you try to compile the DAL project. The compiler will complain it cannot find a range of classes, such as Category and IObjectWithChangeTracker. This is because the generated NorthwindModel.Context.tt code lives in another namespace as the NorthwindModel.tt generated files (which include Category and IObjectWithChangeTracker). So how can we solve this. One way is to tell the code generator to use the same namespace and you can do that by selecting the NorthwindModel.Context.tt file and changing the Custom Tool Namespace property to the namespace of your entities project:

image

Or you could add a using statement to the NorthwindModel.Context.tt file so it generates a using ‘EntityNamespace"’ statement into the generated code (left as an exercise for you, the reader). I like the first solution, since the generated code is only used inside the implementation of the DAL, so using the “wrong” namespace should cause much of a problem. Since your code, which uses the entities will need a using statement anyway, you won’t see any difference in your code.

That’s it.

U2U is still looking for colleagues

Today someone asked my if U2U is still looking for new colleagues, since some time passed since the announcements in popular job-sites.

The answer is YES! If you’d like to join the U2U team, contact us! And maybe you’ll be joining us at TechEd Berlin. The perfect opportunity to get to know each other.

Building a generic EntityViewModel

In this blog post I want to show you a little ViewModel wrapper for entities I’ve built. You can use it to wrap entities who don’t need to support property change notifications, implementing the INotifyPropertyChanged interface. When your model’s entities support INotifyPropertyChanged and IDataErrorInfo, you might find that you don’t need this wrapper, but I would argue that this still simplifies developing application features, such as updating an entity to the latest version from the database (either after a refresh or save command).

The idea is simple, built a class that wraps any object, and which adds the INotifyPropertyChanged and IDataErrorInfo interfaces to it. Normally this would require wrapping the instance, implementing the interfaces and raising the PropertyChanged event in each property’s setter. But using DynamicObject and late binding syntax (dynamic variable declaration) you can save a lot of time by using a little reflection on the wrapped object.

This technique shines when using MVVM, because this pattern works best (even requires) entities to support INotifyPropertyChanged correctly…

DynamicObject has a range of methods used by late binding, and in this wrapper I use the TryGetMember and TrySetMember methods. When you databind to this object, and you bind it to a certain property, then databinding will use TryGetMember to get the properties value, and TrySetMember to update it.

Let'’s start with the class declaration:

public class EntityViewModel<T>
  : DynamicObject, INotifyPropertyChanged, IDataErrorInfo
 

Next we need to add the TryGetMember and TrySetMember methods. Both receive the property name through the binder argument:

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
  PropertyInfo pi = AssertProperty(binder.Name);
  if (pi != null)
  {
    result = pi.GetValue(model, null);
    return true;
  }
  result = null;
  return false;
}

public override bool TrySetMember(SetMemberBinder binder, object value)
{
  PropertyInfo pi = AssertProperty(binder.Name);
  if (pi != null)
  {
    pi.SetValue(model, value, null);
    RaisePropertyChanged(binder.Name);
    return true;
  }
  return false;
}

Both use a PropertyInfo instance to get and set the property’s value. Also note that the TrySetMember method raises the PropertyChanged event:

public event PropertyChangedEventHandler PropertyChanged;

private void RaisePropertyChanged(string propName)
{
  if (PropertyChanged != null)
    PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
 

In a previous post I described how you could implement this interface without hard-coded strings, but in this case all strings are passed as arguments…

To make this more efficient, the PropertyInfo information is cached, so we don’t need to reflect on the type each time. I must admit that I should try measuring if this actually speeds things up, but I need the cache anyway when updating the whole instance, more on this later. Caching is done using a little dictionary:

private static Dictionary<Type, Dictionary<string, PropertyInfo>> cache =
  new Dictionary<Type, Dictionary<string, PropertyInfo>>();


This static dictionary maps a type to another dictionary of string to PropertyInfo. In the constructor we retrieve the object’s type and initialize the dictionary if necessary:

private T model;




public EntityViewModel(T model)
{
  if (model == null)
    throw new ArgumentNullException();
  this.model = model;
  Type type = typeof(T);
  if (!cache.ContainsKey(type))
    cache.Add(type, new Dictionary<string, PropertyInfo>());
}

This cache is used by the AssertProperty method, which retrieves the PropertyInfo from the cache (and maybe its it to the cache).

private PropertyInfo AssertProperty(string propName)
{
  Dictionary<string, PropertyInfo> dict = cache[typeof(T)];
  if (!dict.ContainsKey(propName))
  {
    dict[propName] = typeof(T).GetProperty(propName);
  }
  return dict[propName];
}

So why go through all of this trouble? To wrap instances that do not support INotifyPropertyChanged. This way any change to an instance will have to pass through the wrapper, notifying any interested party, which is normally the databinding engine. For example, should you have a Category class with automatic properties, then databinding will not function correctly when using two-way data binding. However when you wrap the instance with this wrapper then suddenly it will. To make this wrapping easier I have a little extension method to wrap a collection of these objects into an ObservableCollection:

public static class EntityViewModelExtensions
{
  public static ObservableCollection<EntityViewModel<T>> Wrap<T>(this IEnumerable<T> coll)
    where T : IObjectWithChangeTracker
  {
    return new ObservableCollection<EntityViewModel<T>>( coll.Select(el => new EntityViewModel<T>(el)));
  }
}
 

For example, to wrap a List<Category> into ObservableCollection<EntityViewModel<Category>> we can use this (just call Wrap()):

Categories = ProductsBLL.GetCategoryList().Wrap();
 

Another interface implemented by this class is the IDataErrorInfo interface, which is used to attach errors to entities. For full support your entity should implement this interface too, since the errors should flow between layers. So your business layer should support this interface, and use it for storing validation errors.

Finally, imagine you have a list of entities in your application, and the presentation layer shows a list of items. You call a method which returns a new copy of one of the items. How can you merge this item in the existing list? You could remove the old entry, and add the fresh copy in its place. But should there exist another entry to this object than you will have two instances in memory which will be a very confusing bug. Of you copy the fresh data into the existing entity, which requires code to copy each property (a little like DataSet’s Merge method). With the wrapper you simply replace the wrapper’s Model property which will notify all bindings to update:

public T Model
{
  get { return model; }
  set { model = value; RaiseAllUpdated(); }
}

 
internal void RaiseAllUpdated()
{
  foreach (var pair in cache[typeof(T)])
  {
    RaisePropertyChanged(pair.Key);
  }
}
 

This method will raise the PropertyChanged event for each property in it’s cache. This means that only data-bound properties will be updated.

To conclude: here is the complete class

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Dynamic;
using System.Reflection;

namespace U2U.MVVM
{
  public class EntityViewModel<T>
    : DynamicObject, INotifyPropertyChanged, IDataErrorInfo
  {
    private static Dictionary<Type, Dictionary<string, PropertyInfo>> cache =
      new Dictionary<Type, Dictionary<string, PropertyInfo>>();

    private T model;

    public T Model
    {
      get { return model; }
      set { model = value; RaiseAllUpdated(); }
    }

    public EntityViewModel(T model)
    {
      if (model == null)
        throw new ArgumentNullException();
      this.model = model;
      Type type = typeof(T);
      if (!cache.ContainsKey(type))
        cache.Add(type, new Dictionary<string, PropertyInfo>());
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
      PropertyInfo pi = AssertProperty(binder.Name);
      if (pi != null)
      {
        result = pi.GetValue(model, null);
        return true;
      }
      result = null;
      return false;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
      PropertyInfo pi = AssertProperty(binder.Name);
      if (pi != null)
      {
        pi.SetValue(model, value, null);
        RaisePropertyChanged(binder.Name);
        return true;
      }
      return false;
    }

    private PropertyInfo AssertProperty(string propName)
    {
      Dictionary<string, PropertyInfo> dict = cache[typeof(T)];
      if (!dict.ContainsKey(propName))
      {
        dict[propName] = typeof(T).GetProperty(propName);
      }
      return dict[propName];
    }

    internal void RaiseAllUpdated()
    {
      foreach (var pair in cache[typeof(T)])
      {
        RaisePropertyChanged(pair.Key);
      }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string propName)
    {
      if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }

    public string Error
    {
      get
      {
        IDataErrorInfo dataErrorInfo = model as IDataErrorInfo;
        if (dataErrorInfo != null)
          return dataErrorInfo.Error;
        else
          return null;
      }
    }

    public string this[string propName]
    {
      get
      {
        IDataErrorInfo dataErrorInfo = model as IDataErrorInfo;
        if (dataErrorInfo != null)
          return dataErrorInfo[propName];
        else
          return null;
      }
    }

    public bool HasErrors
    {
      get
      {
        IDataErrorInfo dataErrorInfo = model as IDataErrorInfo;
        if (dataErrorInfo != null)
        {
          bool hasErrors = dataErrorInfo.Error != null;
          foreach (var pair in cache[typeof(T)])
          {
            hasErrors = hasErrors | (dataErrorInfo[pair.Key]!= null) ;
          }
          return hasErrors;
        }
        return false;
      }
    }
  }
}

 

Feel free to give this wrapper a try (at your own risk!), and please let me know should you discover any problems.