WPF - From Zero to Hero - Part I
I’d like to learn WPF to create a tiny application (something like a TODO list application). This is my first time ever touching Microsoft technologies. That’s why I will document all the steps I take while learning.
Let’s begin… The first thing I need is Visual Studio. After a quick search on google I found Microsoft Visual Studio Express for Windows Desktop.
Here’s the GUI I want to end up with:
Pretty simple, huh?
I created a new Visual C# WPF Application project and began playing a bit with the Designer. Obviously, since this was my first attempt it didn’t look very good. Besides, I want to add each item (line with image, small description and recommendations) dynamically. This means I have to create some kind of component or a template which I can refer to from code.
After a bit of googling and looking at sample projects I was a bit disappointed with what I found… The most relevant information I have found is in this stackoverflow answer which provides some very good links for data binding and data templating.
Nice looking interface
While the information I found is very good, I still don’t know how to make good looking items. That’s why I began googling for some professional “WPF components” and I found Telerik (a company that seems to specialize in creating various GUI components). After looking a bit on their site I found a demo to download.
Playing with their demos, I noticed they have some examples for a custom ListBox and they also have code samples. The ListBox I found looks somewhat similar to what I want to do:
After checking the source code I saw that they obviously use their own components, but I also noticed that some parts could be used in a standalone project (without Telerik).
But, of course, I had to actually try and see if the components are as independent as I thought they were. That’s why I replaced the empty Grid I got when I created the WPF Application with the one from Telerik examples (section 3. in the image above).
After doing so, I noticed that there were some issues (code underlined with blue wiggles) which are related to some resources I haven’t copied. This and the fact that the window rendering from the upper half of Visual Studio is quite empty and I couldn’t figure out the layout easily, made me remember a useful technique for debugging layouts. The basic idea is to add a bright and noticeable background color to the component you’re debugging so that you can better notice overflows and floating issues.
This is what I got after replacing all those wiggly underlines with the debug background colors:
This kinda looks similar to one of the lines from the Telerik demo (it’s just a bit stretched on height as you can notice from the huge green rectangle): circle on left side, then a title and a small description, and then another image:
Now, at least, I know I got the layout right and it works outside of Telerik.
Code
Here’s the part that creates the (future) item template:
This code also contains the data binding part which seems to use it’s own little language.
I found that these how-to articles and in particular this one about how to make data available for binding in XAML were quite useful in understanding how everything fits together.
The next step is to create the data template for one item.
The basic idea is to put the DataTemplate in the resources part of the application. I saw in some examples that people put these in a separate file, but I’ll do it in the same file for simplicity (and this is just a learning project anyway).
The x:key
part is used to give an identifier for the DataTemplate so you can
later reference it and the DataType
sets the object types that can be
represented using this template.
This is where I stumbled I bit since there were different examples on the
Internet: src:Something
or local:Something
or even c:Something
. I
couldn’t understand how and where are those defined.
I figured it out in the end after a bit of swearing. It looks like you should
define it using XML namespaces (the xmlns part) like this:
xmlns:src="clr-namespace:DiagnoseTry1"
. Only after you do this you can
reference classes inside that namespace using this syntax: src:Item
.
Here are all the puzzle pieces:
That’s why the DataType="src:Item"
part works:
Oh, by the way, in case you’re wondering: CLR is the Common Language Runtime, some kind of a virtual machine used to run .NET programs and it’s similar to the JVM (Java Virtual Machine).
So, probably I can extract a good practice here: to use the same XML
namespace as CLR namespace. That means in my case I would need to use
xmlns:DiagnoseTry1="clr-namespace:DiagnoseTry1"
(besides coming up with
better names for namespaces; at least for this project it doesn’t matter
this much since I’m just learning).
And now here’s the part that uses the DataTemplate
:
ItemTemplate="{StaticResource itemTemplate}"
:
Now follows the part where I couldn’t find more walls where to bang my head.
The binding to a list of items is simply done in XAML, just:
ItemsSource="{Binding items}"
. It’s just that the binding doesn’t work
without a DataContext. What follows is a hack due to not having enough
knowledge to do it the right way in this post.
Normally the DataContext
should be set in XAML code, but this doesn’t work in
MainWindow.xaml
(it causes a StackOverflow exception):
If I set the DataContext
from the C# code then it works:
After reading the explanation from the above mentioned StackOverflow post I understood that I have to use the MVVM pattern. So, the next part will focus on the MVVM pattern and how to use it in WPF.
Result for the first part
I know that this is pretty laughable, but this is what I got working for this first part:
Tips
Use CTRL + E, D to format the XAML and C# code.
Resources
- my laughable attempts on GitHub
- Microsoft Visual Studio Express for Windows Desktop
- the site I used to create the gui sketch
- the StackOverflow answer which gave me the push in the right direction
- Microsoft Data Binding Documentation
- Microsoft Data Templating Documentation
- Telerik Demo I used as example
- .gitignore for all languages and tools
- .gitignore for Visual Studio
- WPF Grid tutorial
- Solution and Project Basics
- WPF video tutorial
- the StackOverflow answer explaining the DataContext
- binding fails with MainWindow (StackOverflow)