Different ways to dynamically select DataTemplate for WPF ListView
Introduction
Recently I get a chance to work on a project in which requirement was to select different different types of data templates based on the data. I faced bit difficulty, but afterwards I was manage to get it work.
Problem Definition
Let's have a look at the scenario first: Inside a WPF ListView, there are two GridViewColumns for storing Name and Age. Now requirement is to highlight the name of the person based on certain age criteria. If age is below 25, then name should be highlighted as red else it should be in green color, with desired background. I know there are ways to implement this using the concept of triggers, but I personally refrain from using triggers due to performance fall back.
Solution
The option left was dynamically selecting data templates. In this post I am going to present two different approaches in which one is the simplest approach and later on I'll do the same thing using Dictionary. Well, let's begin with our code.
Approach 1:
First of all, I created a class named Employee and added some data which will be displayed on UI. Code to perform this is as:
http://3.bp.blogspot.com/-m_VVWKTzmak/Ut7lKIJxZrI/AAAAAAAAAR0/diRPqrNg4mE/s1600/1.png
Next thing, I did is, defined the two DataTemplate in XAML as:
http://2.bp.blogspot.com/-mmqZsbaEW2c/Ut7llLCDRVI/AAAAAAAAAR8/EAEAi6kUdcQ/s1600/2.png
Once the data templates are defined, next task is to figure out the way on how to select the data templates dynamically. So, to perform this task, Microsoft provide us with the class called DataTemplateSelector. Using this class, one can select the data templates based on the business requirement and here is the code:
http://2.bp.blogspot.com/-Z3r5HgqA5Hw/Ut7mn0CV9mI/AAAAAAAAASI/liRuBXxkTqY/s1600/3.png
Next task is to bind this newly created class named MyTemplateSelector with out XAML. So, in order to perform this task, I created a **ResourceDictionary **and kept both the data templates inside it as:
http://2.bp.blogspot.com/-AgJRhVAQS58/Ut7nqj97lAI/AAAAAAAAASU/ZXzjUirskR0/s1600/4.png
Till here we are almost done. The only thing pending is binding our ListView control to collection and setting the cell template, which can be done as:
http://4.bp.blogspot.com/-ljjkMxhJSSo/Ut7orwg-_WI/AAAAAAAAASg/GUGXyXnhOXE/s1600/5.png
Once everything is in place, we will get the desired output:
http://3.bp.blogspot.com/-04vN7hBmp9o/Ut7pQ23rnuI/AAAAAAAAASo/gg48Xvphv6w/s1600/6.png
All the above thing can be done by inheriting **MarkupExtension **class also. So, let's look into that approach.
Approach 2: Using MarkupExtension:
Here I am discussing about the alternative way to achieve the same goal. But here, to make the example simple, I am going to display only Employee names as shown below:
http://3.bp.blogspot.com/-N-nZs-9EqxA/Ut_M9K2z5tI/AAAAAAAAAS8/HuNBJDKnAXI/s1600/1.1.png
Now this to achieve this, I am going to inherit MarkupExtension class provided by Microsoft. This class will give me the DataTemplate. If you will explore further, you will came to know that this MarkupExtension class has only one method named as **ProvideValue, **which will return me the appropriate template based on the supplied value.
Before inheriting MarkupExtension, I created a class named MyDataTemplateDictionary, which will inherit Dictionary<object, DataTemplate>. Please note, here key will be my DataTemplate name and value will be the DataTemplate. Below is the code depicting the same:
http://3.bp.blogspot.com/-5P0EQyNADPw/Ut_O-m6CRMI/AAAAAAAAATI/iVB8WhKT7D4/s1600/1.2.png
Next comes is the class inheriting MarkupExtension. As there is nothing much to explain in this code, I'm directly showing it:
http://4.bp.blogspot.com/-7yLosbMYuFs/Ut_QQx1NaKI/AAAAAAAAATU/8abrZjun5xU/s1600/1.3.png
And finally the class inheriting DataTemplateSelector, which is exactly the same code as shown in previous post:
http://2.bp.blogspot.com/-z83DksXDljg/Ut_R8XF0IpI/AAAAAAAAATg/l0345C8mqfI/s1600/1.4.png
And last but not the least, our XAML:
http://1.bp.blogspot.com/-uSW8_MaHKlI/Ut_ShpavcaI/AAAAAAAAATo/c29mMMXnsG4/s1600/1.5.png
And we are done. Isn't it the cleaner approach?