Tag Archives: resharper

My WPF/MVVM “must have” part 2/ 3 – No Resharper binding error in XAML code

This second post of the “WPF must have” series deals with Resharper and its ability to find binding errors in XAML.

Resharper is a well known Visual Studio plugin used by many.NET developers. It’s a great productivity tool developed by Jetbrains. Even if Resharper (abbreviated in R#) handles javascript and other languages such as VB.NET, I would say that R# is a must when it comes to C#. In addition, we will see in this post that it is also really adapted to XAML editing.

If you have followed my previous post regarding WPF and MVVM, you saw that the ViewModels (VMs), consumed by the Views (composed essentially of XAML code), are proposed by ViewModel locators, for top level VM, or by ViewModel properties. In all cases, we always manipulate the VMs through C# interfaces. This has two major advantages, the first one being the ability to work with design time data (see the first post of the series) and, the second one, to leverage unit testing (this will be the topic of the third post of the series). In addition, specifying the DataContext (i.e. the ViewModel) of a given view through an interface is particularly well adapted to R# usage in XAML.

Let us have a look at the MainWindow.xaml designer and its XAML source taken from my usual sample application DesignableMVVMSample. The vertical bar next to the XAML code is the R#’s warning/error notification zone. My recommendation is to keep the error count to zero so that the XAML file status stays always to full green (no warning, no error).

Zero error in R# warning and error bar

Zero error in R# warning and error bar

The extremely cool feature is that you will benefit from an extension of Visual Studio’s intellisense provided by R#. The interface IMainViewModel exposes a property called AvailablePersons. See in the picture below: all the properties of the ViewModel’s interface (AvailablePersons and BooksWrittenTabViewModel) are now proposed in bold, to distinguish them from the UserControl’s Dependency Properties.

R# augmented Intellisense

R# augmented Intellisense provides ViewModel members for DataBinding.

In addition, this works very well with the strongly typed translation mechanism that I presented in this previous post. Remark that all available translations are now proposed by R# and if you try to use a non translated string you will get a binding error.

Error with translations bindings

Error with translations bindings

As usual with Resharper options, you can disable them at several level: team level, solution level etc. , but more importantly, you can ignore them just once. Indeed, sometimes R# gets wrong and you may want to disable the warning/error. When you click the error you have the possibility to do this by adding the following comment in XAML. <!– ReSharper disable once Xaml.BindingWithContextNotResolved –>. Obviously, this should be exceptional, if you use this too often there is something suspicious in your code.

Let us finish by one tip. R# can detect binding error with “sub datacontext”, however,  within a DataTemplate, Resharper is not always able to recognize well the DataContext type and will raise binding errors where there are none. The trick to avoid such errors is to “force” the DataType in the DataTemplate, see the sample below.

When the DataType is specified within DataTemplate, you can continue to use R# intelisense

When the DataType is specified within DataTemplate, you can continue to use R# intelisense

When developing our product KAssistant, a legal management software fully integrated within MSOutlook, my associate Grégoire who is not a C# expert, was handling most of the work regarding the design and the views in XAML. Early binding errors detected by Resharper was of a great help and saved us a lot of precious time to focus more on the features of our product.

String localization for XAML and C# using dynamically implemented interface

In this post I will describe a solution for easy localized strings management in XAML or C#. Precisely, we will use the usual recommended material for manipulating localized strings in .NET: resx files and the ResourceManager class. However, for XAML manipulation, we will add a “type layer” on top of this. We will see that having typed resources can be very useful. The “type layer” is basically an interface where string properties contain the localized strings, then in XAML or C# code the translations are accessed by using directly these properties. To avoid painful repetitions, the implementation of the interface is dynamically generated using some very simple MSIL. To conclude, we will write simple unit tests that check that the translation files (.resx) contains all the localized strings for all supported languages.

First, let us recall that it is really important that your localized strings are not dispersed in the source code of your application. Using a code snippet of the following form is a bad practice.

//don't do this
TextBox.Text = LocalizeUtil.Localize("Hello","Bonjour","Bon dia");

Indeed, it is very important that you keep grouped all the translations for a given language in one file. Then, you could rework your translations on your own or with a professional without having to grep the entire code base.

Fortunately, .NET comes with all the material you need to handle Culture-Specific resources with the ResourceManager. Say you support english (default) and french languages then you have two .resx files which contains key/value string entries. Such files are named LocalizedStrings.resx and LocalizedStrings.fr-FR.resx they may contain, among others, the entry SayHello (“Hello!” in english and “Bonjour !” in french). Finally, you only have to initialize the ResourceManager and getting the localized strings as follows.

var rem = new ResourceManager("LocalizedStrings", Assembly.GetExecutingAssembly());
Console.WriteLine(rem.GetString("SayHello"));

It is important to note that the right file (*.resx or *.fr-FR.resx) is automatically chosen using the Tread.CurrentThread.CurrentUICulture.

When manipulating XAML for the UI of your app, creating a type for the localized string is recommended. Indeed, in XAML you can bind to properties but you cannot (at least not easily) bind to methods. So the recommended method from the MSDN is to create a LocalizedStrings class whose members are the localized strings.

So we can create the LocalizedStrings class

public class LocalizedStrings
{
    private readonly ResourceManager _rem
    public LocalizedStrings(ResourceManager rem)
    {
        _rem = rem;
    }

    public string SayHello
    {
       { get {return _rem.GetString("SayHello"); }
    }

    public string SayHelloAgain
    {
       { get {return _rem.GetString("SayHelloAgain"); }
    }

    /* A lot of properties more..... */
}

While the instance is retrieved using a Singleton-like pattern (there is no reason to mock this for testing so it makes sense to use a singleton here).

public class StringLocalizer
{
    private static LocalizedStrings _localizedStrings;

    public static LocalizedStrings Strings
    {
        get
        {
            if (_localizedStrings == null)
            {
                  _localizedStrings = new LocalizedStrings(new ResourceManager("LocalizedStrings", Assembly.GetExecutingAssembly())));
             }
             return _localizedStrings;
        }
     }
}

We can use easily the LocalizedStrings in the xaml after adding the StringLocalizer has an application resource.

<!-- set the localizer has a resource -->
 <Application.Resources>
   <local:StringLocalizer xmlns:local ="clr-namespace:appNamespace"
                           x:Key="Localizer" />
 </Application.Resources>
 <!-- in the window or user control -->
 <Button DockPanel.Dock="Left"
         Command="{Binding Next}"
         ToolTip="{Binding Strings.SayHello, Source={StaticResource Localizer}}">

Obviously we can use the same class in the plain old C#

Console.WriteLine(StringLocalizer.Strings.SayHello);

Using this “type layer” is not only mandatory for XAML it is also very useful because we benefit from the static typing. Indeed, typing help us to create localized strings list that do not contain tons on unused entries. Even if this is not a matter of life or death, it is a good thing to remove unused localized strings from your dictionaries, because they going to cost you some effort or money when you will make new languages available or if you want to review the terminology used in your application. The only thing you have to do is to search for unused member of the class (the plugin Resharper does this well even in XAML).

As shown in the image below the XAML-intellisense of Resharper shows us all members of the interface which is handy to reuse localized strings.

The plugins resharper shows all properties of the LocalizedStrings class

The plugins resharper shows all properties of the LocalizedStrings class

Still there is one thing which is cumbersome, every-time you create a new entry you have to type the same logic for the property: _rem.GetString(“NameOfTheProperty”). Then, it’s time to be nerdy and find a way to do this automatically! Let us replace the LocalizedStrings class by and interface ILocalizedStrings whose implementation is dynamically generated. You can emit dynamically new type in .NET using the ILGenerator. So this is the implementation of the new StringLocalizer with some help from the .NET IL guru Olivier Guimbal.

So here it is what the interface looks like

public interface ILocalizedStrings
{
    void SetResMan(ResourceManager man);

    string SayHello{ get; }
    string SayHelloAgain{ get; }
    /* A lot of properties more..... */
}

And here is the StringLocalizer

public class StringLocalizer
{
    private static class InstanceGenerator
    {
        static readonly Dictionary<Type, ILocalizedStrings> Implementations = new Dictionary<Type, ILocalizedStrings>();
        static int _implCount = 0;

        static ModuleBuilder _moduleBuilder;
        static ModuleBuilder ModuleBuilder
        {
            get
            {
                if (_moduleBuilder != null)
                    return _moduleBuilder;
                var assemblyName = new AssemblyName { Name = "Services" };
                AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
                _moduleBuilder = assemblyBuilder.DefineDynamicModule("ServicesModule", "ServicesModule.dll");
                return _moduleBuilder;
            }
        }

        public static ILocalizedStrings CreateImplementation()
        {
            Type interfaceType = typeof(ILocalizedStrings);
            if (!interfaceType.IsInterface)
                throw new ArgumentException(interfaceType + " is not an interface type");

            ILocalizedStrings found;
            if (Implementations.TryGetValue(interfaceType, out found))
                return found;

            var module = ModuleBuilder;
            var tb = module.DefineType(interfaceType.FullName + "Impl" + (_implCount++), TypeAttributes.Public | TypeAttributes.BeforeFieldInit, typeof(object), new[] { interfaceType });

            FieldBuilder fld = tb.DefineField("_resourceManager", typeof(ResourceManager), FieldAttributes.Private);

            var setter = tb.DefineMethod("SetResMan", MethodAttributes.Public | MethodAttributes.Virtual, CallingConventions.HasThis, typeof(void), new Type[] { typeof(ResourceManager) });
            MethodInfo setMethodInfo = typeof(ILocalizedStrings).GetMethod("SetResMan");

            var setterIl = setter.GetILGenerator();
            setterIl.Emit(OpCodes.Ldarg_0);
            setterIl.Emit(OpCodes.Ldarg_1);
            setterIl.Emit(OpCodes.Stfld, fld);
            setterIl.Emit(OpCodes.Ret);

            tb.DefineMethodOverride(setter, setMethodInfo);

            var props = interfaceType.GetProperties();

            foreach (var pi in props)
            {
                if (pi.PropertyType != typeof(string))
                    throw new ArgumentException("Only string properties are supported");

                if (pi.CanWrite)
                    throw new ArgumentException("Property must be read-only: " + interfaceType + " -> " + pi.Name);

                MethodInfo methodInfo = pi.GetGetMethod();
                var mb = CreateOverride(tb, methodInfo);

                var il = mb.GetILGenerator();
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, fld);
                il.Emit(OpCodes.Ldstr, pi.Name);
                il.Emit(OpCodes.Call, typeof(ResourceManager).GetMethod("GetString", new[] { typeof(string) }));
                il.Emit(OpCodes.Ret);

                PropertyBuilder pb = tb.DefineProperty(pi.Name,
                       PropertyAttributes.HasDefault,
                        CallingConventions.HasThis, methodInfo.ReturnType,
                        methodInfo.GetParameters().Select(p => p.ParameterType).ToArray());
                pb.SetGetMethod(mb);
            }

            found = (ILocalizedStrings)Activator.CreateInstance(tb.CreateType());
            Implementations.Add(interfaceType, found);
            return found;
        }

        static MethodBuilder CreateOverride(TypeBuilder tb, MethodInfo mi)
        {
            var mb = tb.DefineMethod(mi.Name,
                        MethodAttributes.Public
                        | MethodAttributes.HideBySig
                        | MethodAttributes.NewSlot
                        | MethodAttributes.Virtual
                        | MethodAttributes.Final,
                        CallingConventions.HasThis, mi.ReturnType, mi.GetParameters().Select(p => p.ParameterType).ToArray());
            tb.DefineMethodOverride(mb, mi);

            return mb;
        }
    }

    private static ILocalizedStrings _localizedStrings;

    public static ILocalizedStrings Strings
    {
        get
        {
            if (_localizedStrings == null)
            {
                _localizedStrings = (ILocalizedStrings)InstanceGenerator.CreateImplementation();
                _localizedStrings.SetResMan(new ResourceManager("LocalizedStrings", Assembly.GetExecutingAssembly())));
            }
         return _localizedStrings;
        }
    }
}
Tests are failing because some properties of the ILocalizedStrings are missing in the resx.

Tests are failing because there are some unused entries in the resx.

To conclude let us write unit tests to ensure that all properties in the interface ILocalizedStrings are defined on all .resx files and, reciprocally, to make sure that all keys in the resx files are properties of the interface. This will help us to track non translated entries and to remove useless keys in the resx dictionaries. We basically parse the .resx files to retrieve all keys and use reflexion to get all public properties of the interface. The test fail when problematic entries are discovered and printed in the test console.

[TestClass]
public class TranslationTests
{

   private TestContext _testContextInstance;
   public TestContext TestContext
   {
       get
       {
           return _testContextInstance;
       }
       set
       {
           _testContextInstance = value;
       }
   }

   private void TestPropertiesAndResxKeyAreEqual(string filePath)
   {
       XDocument xDoc = XDocument.Load(filePath);

       HashSet<string> resxKeys = new HashSet<string>(xDoc.Descendants("data").Select(c => c.Attribute("name").Value));
       HashSet<string> interfaceProp =
           new HashSet<string>(
               typeof (ILocalizedStrings).GetProperties(BindingFlags.Public | BindingFlags.Instance)
                   .Select(p => p.Name));

       bool fail = false;
       foreach (var r in resxKeys)
       {
           if (!interfaceProp.Contains(r))
           {
               _testContextInstance.WriteLine(string.Format("The key {0} exists in resx but not in interface", r));
               fail = true;

           }
       }

       foreach (var property in interfaceProp)
       {
           if (!resxKeys.Contains(property))
           {
               _testContextInstance.WriteLine(string.Format("The key {0} exists in interface but not in resx", property));
               fail = true;
           }
       }
       if (fail)
       {
           Assert.Fail();
       }

   }

   [TestMethod]
   public void TestEnglishResx()
   {
       const string path = @"../../../MyApp/LocalizedStrings.resx";
       TestPropertiesAndResxKeyAreEqual(path);
   }

   [TestMethod]
   public void TestFrenchResx()
   {
       const string path = @"../../../MyApp/LocalizedStrings.fr-FR.resx";
       TestPropertiesAndResxKeyAreEqual(path);
   }
}

A generic version of ICollectionView used in a MVVM searchable list

In this post we will describe how to create a searchable list with WPF following MVVM principles. To this aim we will use a WPF ListView to display the searched items and a TextBox to enter the text used for the search. Most of the implementation that you will find on the web (e.g. this one) will recommend you to bind your ListView to an ICollectionView. However, this is not 100% satisfactory as long as ICollectionView does not have a built-in generic version. Consequently the ViewModel’s member exposing the binding items will return an ICollectionView which is a powerful object (see this for instance)  but is “only” an enumeration of System.Object. In this post we will show you that a generic version can be easily implemented and exposed by your ViewModel.

In this post we will create a very simple app that let you search a player in the list of all the players of the last Football World Cup in Brazil. The complete source code can be found on my Github here.

Searchable WPF ListView

Searching ‘dav’ in the ListView display a list of results starting with ex Chelsea’s player David Luis…

The key ingredients of such implementation is very simple in MVVM. First take the View which does not need more than the few lines of xaml below.

 <UserControl.DataContext>
 <Binding Path="PlayerSearchViewModel" Source="{StaticResource Locator}" />
</UserControl.DataContext>
<DockPanel>
 <TextBlock DockPanel.Dock="Top" Text="Search player"></TextBlock>
 <TextBox DockPanel.Dock="Top" Text="{Binding SearchPlayerText, UpdateSourceTrigger=PropertyChanged}"></TextBox>
<ListView ItemsSource="{Binding DisplayedPlayers}" SelectionMode="Single" ScrollViewer.VerticalScrollBarVisibility="Auto">
  <ListView.View>
   <GridView >
    <GridViewColumn DisplayMemberBinding="{Binding Name}" Header="Name" />
    <GridViewColumn DisplayMemberBinding="{Binding NationalTeam}" Header="National Team" />
    <GridViewColumn DisplayMemberBinding="{Binding Age}" Header="Age" />
    <GridViewColumn DisplayMemberBinding="{Binding Club}" Header="Club"/>
    <GridViewColumn DisplayMemberBinding="{Binding Championship}" Header="Championship"/>
   </GridView>
  </ListView.View>
 </ListView>
</DockPanel>

Let us start by exposing the non-generic version: the DataContext of the control above is bound to an instance of an implementation of the interface IPlayerSearchViewModel below.

public interface IPlayerSearchViewModel
{
   string SearchPlayerText { get; set; }

   ICollectionView DisplayedPlayers { get; }
}

A very straightforward implementation that works is the following one.

public class PlayerSearchViewModel : IPlayerSearchViewModel
{
    private readonly ICollectionView _view;
    private string _textsearch;

    public PlayerSearchViewModel(IPlayerProvider playerProvider)
    {
        _view = CollectionViewSource.GetDefaultView(playerProvider.GetAllWorldCupPlayer());
        _view.Filter += (object item) =>
        {
                    if (_textsearch == null) return true;
                    var itemPl = (IPlayer) item;
                    return itemPl.Name.Contains(_textsearch) ||
                               itemPl.NationalTeam.Contains(_textsearch) ||
                               itemPl.Club.Contains(_textsearch) ||
                               itemPl.Championship.Contains(_textsearch);
        };
    }

    public string SearchPlayerText
    {
        get { return _textsearch; }
        set
        {
            _textsearch = value;
            _view.Refresh();
        }
    }

    public ICollectionView DisplayedPlayers { get { return _view; } }
}

As I said in the introduction, this is quite enoying. You may want to create screens with many ICollectionView bindings that may contain different types, then it is becoming error prone and we are loosing the benefit of C#’s type safety. The unit test example below is showing you that the elements need to be casted while they are accessed from the ICollectionView.

[TestMethod]
public void TestingTheSearchingCapabilitiesWithBedoya()
{
    var viewModel = new PlayerSearchViewModel(new PlayerProvider());
    viewModel.SearchPlayerText = "Bedoya";
    var searchResult = viewModel.DisplayedPlayers.Cast<IPlayer>().ToArray(); //Cast objects extracted from the ICollectionView
    Assert.AreEqual(1, searchResult.Length);
    IPlayer bedoya = searchResult[0];
    Assert.AreEqual("Nantes",bedoya.Club);
}

In addition we cannot use anymore the XAML validation and intellisense provided by Resharper.

Resharper complaining because of the unknown's member of the DataContext (typed as object)

Resharper complaining because of the unknown’s member of the DataContext (typed as object)

Fortunately we can create our generic version of ICollectionView and get back to the comfortable world of type safety. In this example, I will only provide the generic enumeration and the generic version for the SourceCollection member but you can add others. Indeed, you may create a generic version of the Filter predicate to avoid dealing with System.Object in your lambdas but with your generic type T instead.

public interface ICollectionView<T> : IEnumerable<T>, ICollectionView
{
    IEnumerable<T> SourceCollectionGeneric { get; }
    //Add here your "generic methods" e.g.
    //e.g. Predicate<T> Filter {get;set;} etc.
}

Actually, the implementation of the ICollectionView is really easy as long as you already have the non-generic instance at hand ICollectionView

public class MyCollectionViewGeneric<T> : ICollectionView<T>
{
    private readonly ICollectionView _collectionView;

    public MyCollectionViewGeneric(ICollectionView generic)
    {
        _collectionView = generic;
    }

    private class MyEnumerator : IEnumerator<T>
    {
        private readonly IEnumerator _enumerator;
        public MyEnumerator(IEnumerator enumerator)
        {
            _enumerator = enumerator;
        }

        public void Dispose()
        {
        }

        public bool MoveNext()
        {
            return _enumerator.MoveNext();
        }

        public void Reset()
        {
            _enumerator.Reset();
        }

        public T Current { get { return (T) _enumerator.Current; } }

        object IEnumerator.Current
        {
            get { return Current; }
        }
    }

    public IEnumerator<T> GetEnumerator()
        {
            return new MyEnumerator(_collectionView.GetEnumerator());
        }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return _collectionView.GetEnumerator();
    }

    public bool Contains(object item)
    {
     return _collectionView.Contains(item);
    }

    public void Refresh()
    {
        _collectionView.Refresh();
    }

       //Complete implementation can be found on github.co/bpatra/MVVMSample

    public event NotifyCollectionChangedEventHandler CollectionChanged
    {
        add
        {
            lock (objectLock)
            {
                _collectionView.CollectionChanged += value;
            }
        }
        remove
        {
            lock (objectLock)
            {
                _collectionView.CollectionChanged -= value;
            }
        }
    }

    public IEnumerable<T> SourceCollectionGeneric

        get { return _collectionView.Cast<T>(); }
    }
}

Therefore the implementation of the the ViewModel becomes cleaner and statically typed. First the new version of the ViewModel interface.

public interface IPlayerSearchViewModel
{
    string SearchPlayerText { get; set; }

    ICollectionView<IPlayer> DisplayedPlayers { get; }
}

Then, the implementation.

public class PlayerSearchViewModel : IPlayerSearchViewModel
{
    private readonly ICollectionView<IPlayer>; _view;
    private string _textsearch;

    public PlayerSearchViewModel(IPlayerProvider playerProvider)
    {
        _view = new MyCollectionViewGeneric<IPlayer>;(CollectionViewSource.GetDefaultView(playerProvider.GetAllWorldCupPlayer()));
        _view.Filter += (object item) =>;
        {
            if (_textsearch == null) return true;
            var itemPl = (IPlayer) item;
            return itemPl.Name.Contains(_textsearch) ||
                        itemPl.NationalTeam.Contains(_textsearch) ||
                        itemPl.Club.Contains(_textsearch) ||
                        itemPl.Championship.Contains(_textsearch);
        };
    }

    public string SearchPlayerText
    {
    get { return _textsearch; }
        set
        {
            _textsearch = value;
            _view.Refresh();
        }
    }

    public ICollectionView<IPlayer>; DisplayedPlayers { get { return _view; } }
}

You do not have to cast or worry anymore on the the type of the objects contained in you ICollectionView. You will also detect binding errors statically with Resharper.

resharperClever

Resharper handles typed generic collections in databinding