WPF ComboBox Enum automatic Binding and Localization

Use it like this:


<ComboBox
behaviors:ComboBoxEnumBehavior.EnumType="{x:Type ClickMode}"
behaviors:ComboBoxEnumBehavior.ResourceManager="{Binding Source={x:Static resources:MyResources.ResourceManager}}" />

And here is the code:


public static class ComboBoxEnumBehavior

public static ResourceManager GetResourceManager(DependencyObject obj)
{
return (ResourceManager)obj.GetValue(ResourceManagerProperty);
}

public static void SetResourceManager(DependencyObject obj, ResourceManager value)
{
obj.SetValue(ResourceManagerProperty, value);
}

public static readonly DependencyProperty ResourceManagerProperty =
DependencyProperty.RegisterAttached(“ResourceManager”, typeof(ResourceManager), typeof(ComboBoxEnumBehavior), new PropertyMetadata(null, OnChanged));

private static ObservableCollection GetEnumNames(DependencyObject obj)
{
return (ObservableCollection)obj.GetValue(EnumNamesProperty);
}

private static void SetEnumNames(DependencyObject obj, ObservableCollection value)
{
obj.SetValue(EnumNamesPropertyKey, value);
}

private static readonly DependencyPropertyKey EnumNamesPropertyKey =
DependencyProperty.RegisterAttachedReadOnly(“EnumNames”, typeof(ObservableCollection), typeof(ComboBoxEnumBehavior), new PropertyMetadata(null));

private static readonly DependencyProperty EnumNamesProperty = EnumNamesPropertyKey.DependencyProperty;

public static Type GetEnumType(DependencyObject obj)
{
return (Type)obj.GetValue(EnumTypeProperty);
}

public static void SetEnumType(DependencyObject obj, Type value)
{
obj.SetValue(EnumTypeProperty, value);
}

public static readonly DependencyProperty EnumTypeProperty =
DependencyProperty.RegisterAttached(“EnumType”, typeof(Type), typeof(ComboBoxEnumBehavior), new PropertyMetadata(null, OnChanged));

private static void OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ComboBox comboBox = d as ComboBox;
Type enumType = GetEnumType(comboBox);
ResourceManager resourceManager = GetResourceManager(comboBox);
if (comboBox != null && enumType != null)
{
UpdateItemsSourceBinding(comboBox, enumType, resourceManager);
}
}

private static void UpdateItemsSourceBinding(ComboBox comboBox, Type enumType, ResourceManager resourceManager)
{
if (!enumType.IsEnum)
{
throw new ArgumentException(“EnumType must be an System.Enum”);
}
if (enumType != null && comboBox != null)
{
// Fill EnumNames attached property
ObservableCollection enumNames = new ObservableCollection();
foreach (var item in Enum.GetNames(enumType))
{
if (resourceManager != null)
{
// with localization
var key = enumType.FullName.Replace(“.”, “_”) + “_” + item;
var localizedString = resourceManager.GetString(key);
if (string.IsNullOrEmpty(localizedString))
{
enumNames.Add(“??? ” + resourceManager.BaseName + “.” + key);
}
else
{
enumNames.Add(localizedString);
}
}
else
{
// without localization
enumNames.Add(item);
}
}
comboBox.SetValue(ComboBoxEnumBehavior.EnumNamesPropertyKey, enumNames);

// Add Binding for ItemsSource
Binding enumNamesBinding = new Binding();
enumNamesBinding.Path = new PropertyPath(“(0)”, ComboBoxEnumBehavior.EnumNamesProperty);
enumNamesBinding.RelativeSource = new RelativeSource(RelativeSourceMode.Self);
BindingOperations.SetBinding(comboBox, ComboBox.ItemsSourceProperty, enumNamesBinding);

comboBox.IsSynchronizedWithCurrentItem = true;

// Add Binding for SelectedItem
Binding selectedItemBinding = new Binding(“Selected” + enumType.Name);
selectedItemBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
selectedItemBinding.Mode = BindingMode.TwoWay;
BindingOperations.SetBinding(comboBox, ComboBox.SelectedItemProperty, selectedItemBinding);
}

}

}

 

Of course you could turn this into a “real” behavior but I wanted to keep it simple for the post.
Don’t forget the xmlns:behaviors=”clr-namespace:Your.Namespace;assembly=Your.Assemby” in your page / window.
You will need xmlns:resources=”clr-namespace:blabla” for the location of you .RESX as well.
Code will only work if you set “Access Modifier” to “Public” for your .resx file.
(just insert PublicResXFileCodeGenerator as Custom Tool in .resx properties)

How to access private class members using Linq Expressions

This article is intended for cases where you are willing/forced to access a private member of a class.

That means you are not willing/able to change the code that defines the member.

If you need to access the member for many many instances of the class, “GetFieldAccessor” will save your cpu some time.

Properties and methods are accessible by creating “open instance delegates” via Delegate.CreateDelegate.

As discussed here: Use delegate to get values for FieldInfo, “Field access isn’t performed via a method (like getters and setters)–it’s performed with an IL instruction–so there’s nothing you can assign to a delegate. you’ll have to use the expression route to create a “block” of code (effectively IL) that can be assigned to a delegate.”

Previous to the introduction of Linq Expressions, Reflection would have been your only option.

Usage:

public class TestClass
{
    public TestClass(int i) { privateField = i; }
    private int privateField;
}
 
private void Test()
{
    var list = Enumerable.Range(0, 10000000).Select(i => new TestClass(i)).ToList();
    // old way: use FieldInfo
    var fieldInfo = typeof(TestClass).GetField("privateField"BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);
    var w = Stopwatch.StartNew();
    for (int i = 0; i < list.Count; i++)
    {
        var val = (int)fieldInfo.GetValue(list[i]);
        if (val != i)
            throw new InvalidOperationException();
    }
    w.Stop();
    // new way: use Expression.Field
    var accessor = GetFieldAccessor<TestClassint>("privateField");
    var w2 = Stopwatch.StartNew();
    for (int i = 0; i < list.Count; i++)
    {
        var val = accessor(list[i]);
        if (val != i)
            throw new InvalidOperationException();
    }
    w2.Stop();
    // ~ 7%
    Console.WriteLine(100.0 / (w.ElapsedTicks / w2.ElapsedTicks) + "%");
}

Both variants do the expensive Reflection part only once, outside of the for-loop.

The compiled delegate takes less than 10% cpu time. (compared to Reflection)

Here is the code for GetFieldAccessor:

public static Func<T, TResult> GetFieldAccessor<T, TResult>(string fieldName)
{
    var instExp = System.Linq.Expressions.Expression.Parameter(typeof(T));
    var fieldExp = System.Linq.Expressions.Expression.Field(instExp, fieldName);
    return System.Linq.Expressions.Expression.Lambda<Func<T, TResult>>(fieldExp, instExp).Compile();
} 

One last point: If you are forced to use .NET before 3.5 but still need additional performance:

  • Use Reflection.Emit to create a method that returns the private member
  • Then use an open instance delegate

Startnew Is Dangerous

Recently I was developing an ActionQueue. It supports serial asynchronous execution of Sytem.Action<ICancellationToken> delegates. I ran into a problem similar to this: Memory leak in recursive continuation Tasks I have a state object (e.g. of type Tuple<,,,>) and I pass this to Task.Factory.StartNew and if I run a memory profiler on my application I see that those state objects are not GC’ed. (Go is of type System.Action<object>).

// state is never released:
var task = Task.Factory.StartNew(Go, state);
 
// same problem:
var task = new Task(Go, state, TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler);
task.Start(TaskScheduler.Default);

My implementation had the assumption that “task” would represent the entire “Go” method but it represents only the first (synchronous) part if “Go” points to an asynchronous method (one that uses the async keyword). Some additional insight can be found here: http://blog.stephencleary.com/2013/08/startnew-is-dangerous.html The reason for the memory leak is that my implementation spawns continuations whose AsyncState recursively contains information about the previous Task. (In a memory profiler you will probably see its backing field “m_State”) Since you can’t reset the AsyncState property of Task (it is readonly and Dispose() does not clear it) all your Tasks and all their states will stay alive. This will not happen if you capture the state variable by passing a lambda expression to Task.Run:

// this works:
var task = Task.Run(() => Go(state));

So Task.Factory.StartNew is not only dangerous because of the reasons stated by Stephen Cleary, but also because it tempts you to use Task.AsyncState which also can be dangerous.

Multiple Inheritance

I you are developing a somewhat bigger project, sooner or later you will find yourself in a situation when you have already wasted your one and only allowed base class and say “It would be nice if this class could also derive from another one”. Well it wouldn’t. But that is a different story. Still, the problem can be solved in different ways:

Of course just the first one is meant seriously.

Let’s first take a look at why we want inheritance in the first place:

Two reasons: Polymorphism and Maintainability.

In my case the focus lies on maintainability. We do not want to have duplicate code. Or to be more specific, no duplicate code that is handwritten and therefore has an impact on maintainability. T4 templates to the rescue! http://msdn.microsoft.com/de-de/library/ee844259(v=vs.100).aspx 

I have some interfaces that many of my classes (ViewModels in my case) have to implement, and those ViewModels already have a base class. The interfaces are used by central behavior and manager classes that help organizing and unifying the user interface. The implementation of those interfaces is always the same, most of them just define some properties and the implementation takes care of the INotifyPropertyChanged.PropertyChanged event being raised properly.

Here is an example of such an interface:

IExecutableItem.cs

   public interface IExecutableItem
   {
        public ICommand Command { get; set; }
        public object CommandParameter { get; set; }
        public event CommandExecutedEventHandler Executed;
   }

Now with the help of T4 templates you can do this:

1.) Your create a partial class for your ViewModel that contains your handwritten code.

MyViewModel.cs

    public partial class MyViewModel : ViewModelBase
    {
        public MyViewModel(IServiceLocator serviceLocator)
            : base(serviceLocator)
        {  }
        // [ more code ... ]
    }

2.) You create a T4 Template File that generates the implementation of additional interfaces:

MyViewModel.ModelProperties.tt

<#@ template hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ include file="..\ModelProperties\ModelProperties.tt" #>
<#
	Implement(
		@"..\ModelProperties\",
		"ISelectableItem;IExecutableItem;IOrderedItem"
	);
#>

3.) You are done.

To make this work you need the included file ModelProperties.tt and one .tt file per interface you wish to be implementable in this way. I will give you the interface .tt for the IExecutableItem interface as an example:

IExecutableItem.tt

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ import namespace="System.Runtime.Remoting.Messaging" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ parameter name="ClassName" type="System.String" #>
<#@ parameter name="Namespace" type="System.String" #>
<#
	var usings = (List<string>)CallContext.GetData("usings");
	usings.Add("using System.Windows.Input;");
	usings.Add("using MyCompany.MyProject.Tools;");
#>
namespace <#=Namespace#>
{

    public partial class <#=ClassName#> : IExecutableItem
    {

        private ICommand _Command;

        /// <summary>
        /// Command
        /// </summary>
        public ICommand Command
        {
            get { return _Command; }
            set
            {
                if (_Command != value)
                {
                    _Command = value;
                    base.RaisePropertyChanged(() => Command);
                }
            }
        }

        private object _CommandParameter;

        /// <summary>
        /// CommandParameter
        /// </summary>
        public object CommandParameter
        {
            get { return _CommandParameter; }
            set
            {
                if (_CommandParameter != value)
                {
                    _CommandParameter = value;
                    base.RaisePropertyChanged(() => CommandParameter);
                }
            }
        }

        private event CommandExecutedEventHandler _Executed;

        /// <summary>
        /// Executed
        /// </summary>
        public event CommandExecutedEventHandler Executed
        {
            add { _Executed += value; }
            remove { _Executed -= value; }
        }

    }

}

and here is the ModelProperties.tt:

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name = "System.Core" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Runtime.Remoting.Messaging" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#+

		public void Implement(string path, string interfaces)
		{
			TextTemplatingSession session = new TextTemplatingSession();
			session["Namespace"] = "MyCompany.MyProject.Demo";
			session["ClassName"] = "MyViewModel";
			var usings = new List<string>();
			CallContext.SetData("usings", usings);
			var sessionHost = (ITextTemplatingSessionHost) this.Host;
			sessionHost.Session = session;
			foreach (var item in interfaces.Split(';'))
			{
				GenerationEnvironment.Append(ProcessTemplate(Path.Combine(path, item.Trim() + ".tt")));
			}
			this.GenerationEnvironment.Insert(0, Environment.NewLine);
			foreach (var item in usings.Distinct().OrderByDescending(x => x))
			{
				this.GenerationEnvironment.Insert(0, item + Environment.NewLine);
			}
		}

		public string ProcessTemplate(string templateFileName)
		{
			string templateDirectory = Path.GetDirectoryName(Host.TemplateFile);
			string template = File.ReadAllText(Host.ResolvePath(templateFileName));
			Engine engine = new Engine();
			string output = engine.ProcessTemplate(template, Host);
			return output + Environment.NewLine;
		}

#>

The Implement method creates a session and stores the classname and the namespace in it. It also stores a stringlist in the CallContext to allow the interface .tt’s to add usings to the output. Then each interface .tt is executed and the output is added. Finally the content of the using stringlist is made distinct, sorted and inserted at the top of the generated file.

You end up with a ViewModel that has all the implementations from your interface .tt files. I know this is not “real” inheritance but it serves our main goal: Maintainability. Changes in the interface .tt files will be reflected in all “derived” classes once you hit “Transform all templates” again.

You could also combine this idea with the aforementioned “Simulated Multiple Inheritance Pattern” and make your templates generate all the redirecting methods. That way you would end up being able to also extend classes instead of just interfaces. I’ll leave this to you as a an exercise 😉

This is still not an out-of-the-box solution because you have to make all classes and interfaces “implementable” but usually you have only some base classes and interfaces and many many classes deriving from them.