Algorithm for Drawing Trees

April 20, 2014

I recently wanted to take a hierarchy of items and draw them in a nice tree structure. For example, a Family Tree.

At the time, I thought “This will be easy, I’ll just Google for an algorithm to determine the X,Y position of each node, then do something to draw each node on the screen”.

But it turns out Googling for a simple and easy-to-follow algorithm for drawing nice trees is very hard.

My initial Google attempts lead me to the Reingold-Tilford Algorithm.

This sounded exactly like what I wanted, however I was having a lot of trouble in understanding the algorithm so I could convert it into my language of choice (C#). Every article I found seemed to be written for a much smarter person than myself, and I had some difficulty following what they were doing and converting the logic to C#.

After much time spent going through research papers and browsing sample code, I think I finally understand it. So here’s my attempt at explaining the algorithm for drawing trees in an aesthetically pleasing way, using simple terms.

The Example

I’m going to use the example tree from a 1991 journal article by Dr. Dobbs. I found this article the easiest to understand and work my way through, and it would probably be worthwhile to read it if you’re looking into drawing nice trees for yourself. It also contains some more details about what is considered an “aesthetically pleasing tree”, which I won’t talk about in detail because its easy to find online if needed.

The sample tree from the article that I will be using looks like this:

DrawingTrees_FullTree

Introduction to The Algorithm

Determining the Y position of each node is easy, so I’m not going to go into detail about it here. The main trouble is determining an appropriate X position for each node.

Here is a very brief overview of the logic I used to determine an appropriate X position of each node. You could probably just take this and figure out how to get the X,Y values yourself in whatever language you want, or I’ll go into each step in more detail later.

  1. Do a post-order traversal of the tree
  2. Assign an X value to each node of 0 if it’s a left-most node, or leftSibling.X + 1 if it’s not.
  3. For each parent node, we want the node centered over the children. This would be the midway point between the first child’s X position, and the last child’s X position.

    If the parent has no left sibling, change it’s X value to this midpoint value. If it has a left sibling, we’re going to store it in another node property. I’m calling this property Mod just because that’s what I see it called in other examples.

    The Mod property is used to determine how much to modify the children’s X values in order to center them under the parent node, and will be used when we’re done with all our calculates to determine the final X value of each node. It should actually be set to Parent.X – MiddleOfChildrenX to determine the correct amount to shift the children by.

  4. Check that this tree does not conflict with any of the previous sibling trees, and adjust the Mod property if needed. This means looping through each Y level in the current node, and checking that the right-most X value of any sibling to the left of the node does not cross the left-most X value of any child in the current node.
  5. Do a second walk through the tree to determine that no children will be drawn off-screen, and adjust the Mod property if needed. This can happen when if the Mod property is negative.
  6. Do a third walk through the tree to determine the final X values for each node. This will be the X of the node, plus the sum of all the Mod values of all parent nodes to that node.

Now lets go through each step in more detail.

First Traversal of Tree

We’re going to do a pre-order traversal of the tree for the first walk through, meaning we draw the tree from the bottom up, going from left to right. See the initial drawing of the tree? The nodes have letters on them, A through O. This is the order which the post-order traversal will process the nodes.

This iteration of the tree can be broken up into 3 steps:

  • Assign an X value to each node of leftSibling.X + 1, or 0 if no leftSibling
  • Move child nodes under parent node
  • Verify no children conflict with other trees

Assigning initial X values

The first step is to calculate a “local X” value value for each node. This is the X value within that set of children only.

So the X value of each node after this step would look like this:

DrawingTrees_InitialX

The code I use for this is as follows

private void CalculateInitialX(TreeNode node)
{
    foreach (var child in node.Children)
        CalculateInitialX(child);

    // if there is a previous sibling in this set, 
    // set X to prevous sibling + designated distance
    if (!node.IsLeftMost())
        node.X = node.GetPreviousSibling().X + 1;
    else
        // if this is the first node in a set, set X to 0
        node.X = 0;
}

Of course, if we actually drew all the nodes at those X values, they would overlap and you wouldn’t be able to see the tree hierarchy.

DrawingTrees_InitialX_2

So we the next step positions the child nodes under their parent.

The Mod Property

Before continuing, I should explain the “Mod” property.

The rest of these steps can involve shifting a Node and all its children over, sometimes multiple times. To do this, we would normally have to loop through all nodes in that subtree and increase their X values, however this can be bad for performance, especially for larger trees.

So to avoid that, we are using the Mod property to tell the node how far it needs to shift all its children by, and then at the end of this this we will do a second walk through the tree to determine the ultimate X position of the node.

To shift a node and all it’s children over during this iteration, increase both it’s X and Mod properties by however much you want.

Positioning Child Nodes under Parents

The next step is to center the child nodes under the parent node. This is actually pretty easy.

First, find the X value that would center a node over it’s children.

  • If there is 1 child, the desired X value is the same as the child’s X value.
  • If there is more than one child, get the first child’s X and the last child’s X, and find the midway point between the two.

Next, check to see if this is the parent node has any siblings to the left of it. I do this by checking the node’s parent to see if this node is equal to the first node in the parent’s children.

  • If this is the first node in the parent’s children, set the X value equal to the desired X value to center the parent over the children.
  • If not, assign the Mod value of the node to node.X - desiredX to shift children under the parent.

After the third tree traversal is done to calculate the final X values of nodes, this will correctly position the children underneath their parent node.

However it doesn’t stop the trees from overlapping each other. See nodes B, C, H, and I in our tree now?

DrawingTrees_AfterPositioningChildrenUnderParent

Checking for node Conflicts

Once you’ve come this far, this step isn’t as bad as it sounds.

The basic logic is if a node has any children, we need to loop through all levels of children and ensure that none of the X values assigned to that child conflict with any X values assigned to previously positioned children at the same level.

To do this, we loop through all children of the current node, and for each Y value we record the minimum X position. Then for each sibling to the left of this node, we loop through all its children and record the maximum X position at each Y. Google told me there’s a fancy term for this: the tree Contour.

So at the time that node N (Blue) is being processed, its Left Contour is { 1.5, 1, 0.0 }, while the Right Contour of node E (green) is { 0.5, 1.0, 1.5 }.

DrawingTrees_NodeContour

Keep in mind that this check uses the final X of the Node as its been calculated so far, and not the local X that we assigned to it initially.

We can see that both the first and second levels overlap, so we need to shift node N over far enough that its Left Contour no longer conflicts with node E’s Right Contour.

In this case, the largest overlapping distance between the two contours is 1.5, and we want to add an extra 1 to make sure the nodes aren’t drawn on top of each other, so we shift node N over by 2.5 places.

Fixing middle trees after resolving a conflict

The previous step fixed the issue of having overlapping nodes, however the end result leaves a lot of empty whitespace in the middle of the tree. Note the position of node F in the tree now:

DrawingTrees_AfterResolvingConflicts

We shifted node N because it conflicted with E, and now we need to take that distance and apply it evenly across all sibling nodes that are between the two conflicting nodes.

To do that, we divide the distance shifted by the number of nodes between our two conflicting nodes + 1, and shift each of the middle nodes over by this value.

In our case we shifted the node by 2.5, and there is only 1 node (F) between nodes E and N, so we need to shift F over by 2.5 / (1 + 1), which results in 1.25.

And then to be sure we didn’t cause conflicts by shifting the middle nodes, we need to check for conflicts once again.

The end result is the trees will be slightly larger than absolutely necessary, however they will be generated nicely with no conflicting nodes or uneven amounts of whitespace anywhere.

DrawingTrees_FullTree

Second Traversal of Tree

Some nodes can have a negative Mod value, which can position the final X of child nodes at a negative value too, and render them off screen.

For an example, if I shift node N to be positioned under A instead of O, I get this result because node H has an X value of -1:

DrawingTrees_NodeOffScreen

We could check the Mod value at the time it’s calculated to ensure it’s not a negative, however that would only shift our current node over, could resulting in some undesired extra whitespace between sibling nodes.

For example, take a look at the space between nodes G and M in this tree

DrawingTrees_NodeOffScreenBadSolution

The best way to fix this problem is to shift the Root Node over enough so that none of the final X values will be negative.

To do this we can get the Right Contour of the Root Node, find the smallest X value, and if its negative we shift the Root Node over by that amount. Remember, to shift a subtree we adjust both the X value and the Mod value by whatever amount we’re shifting by.

Here’s how my code for this looks

private void CheckAllChildrenOnScreen(TreeNode rootNode)
{
    var nodeContour = new Dictionary<int, float>();
    GetLeftContour(rootNode, 0, ref nodeContour);

    float shiftAmount = 0;
    foreach (var y in nodeContour.Keys)
    {
        if (nodeContour[y] + shiftAmount < 0)
            shiftAmount = (nodeContour[y] * -1);
    }

    if (shiftAmount > 0)
    {
        rootNode.X += shiftAmount;
        rootNode.Mod += shiftAmount;
    }
}

private void GetLeftContour(TreeNode node, float modSum, ref Dictionary<int, float> values)
{
    if (!values.ContainsKey(node.Y))
        values.Add(node.Y, node.X + modSum);
    else
        values[node.Y] = Math.Min(values[node.Y], node.X + modSum);
 
    modSum += node.Mod;
    foreach (var child in node.Children)
    {
        GetLeftContour(child, modSum, ref values);
    }
}

Here’s how the tree looks now after being shifted over to fit all nodes on the screen:

DrawingTrees_AfterFixingNodesOffScreen

Third and Final Traversal

The third tree traversal calculates the final X position of each node by adding the Mod value of all its parent nodes to its X value.

I use a simple recursive function for this

private void CalculateFinalX(TreeNode node, float modSum)
{
    node.X += modSum;
    modSum += node.Mod;

    foreach (var child in node.Children)
        CalculateFinalPositions(child, modSum);
}

Here’s an image of how the final tree’s X values look

Final X Values

Final X Values

(I have decimal numbers in there because I was by positing nodes 1 space apart to make the math easier to follow, and determining the midpoint often resulted in a decimal)

Final Results

Now all that’s left to do is take this tree of objects with X,Y coordinates, and draw it somewhere!

DrawingTrees_FullTree

Final Thoughts

This algorithm is not perfect. I have tested what I could, but I’m sure there’s still bugs in it (I found one while writing this post!). But now I understand how it is supposed to work, and can debug/fix the issues that come up as needed.

The sample code I was using for this project can be downloaded here.

It may not be optimized since it was done for demonstration purposes only, and could be missing some things. It should be thoroughly tested before being used in any kind of production environment.


Understanding the change in mindset when switching from WinForms to WPF

October 12, 2012

One of the biggest hurdles I find WinForms developers struggling with when learning WPF and the MVVM design pattern, is understanding the shift in thought process that is used for WPF/MVVM development.

Here’s the best way I can summarize the difference:

  • In WinForms, your forms and UI objects are your application.
  • In WPF/MVVM, the class objects you build are your application, while UI objects are nothing more than a user-friendly interface for interacting with your application objects.

Example

For example, suppose we were asked to make a simple Registration form that takes down a user’s Name, Email Address, and asks them if they want to receive Special Offers or not.

A WinForms developer’s thought process might be to think “I need a Window that contains a TextBox for name, TextBox for email, CheckBox for if they want special offers or not, and a Button to submit the form. When the Submit button is pressed, the data is taken from the UI objects, and saved to the database.”

Winforms Developer's Thought Process

In contrast, a WPF developer’s thought process is “I need a Window that contains a RegistrationForm object. This class needs a string for the Name, a string for the EmailAddress, a boolean property for if they want special offers or not, and a Command to submit the data.”

WPF Developer's Thought Process

But of course WPF doesn’t know how to draw a class of type RegistrationForm, so we’ll have to tell it how to draw the RegistrationForm object using a Template. This template would probably render the Name and EmailAddress properties using TextBoxes, the IsSpecialOffers property with a CheckBox, and provide a Button to run the SaveDataCommand, although that doesn’t have to be the case and is something that can be figured out later.

With WPF, the UI layer and the application layer are so completely separated that you don’t actually need the UI layer at all. If you wanted, you could run your application entirely by test scripts, or through a console window. The actual application layer never needs to reference any UI object to get its data.

Using this concept on a larger scale

In fact, this thought process is used on a much broader scale for the entire WPF/MVVM application.

Want a LoginWindow to come up, and on successful login switch to the MainWindow? No problem, simply start the program with your LoginClass, and on successful Login return the ApplicationClass.

Want to have an application with separate Windows for Products, Orders, and Customers? No problem, create your ApplicationClass to hold a List<T> of available “Window” objects containing the classes representing each “Window”, and include a SelectedWindow property which identifies which window object is currently active.

Of course, WPF needs to know how to draw these class objects, so you’ll need to tell it to use a specific DataTemplate, UserControl, Page, or maybe even Window when rendering these objects.

Summary

This is not meant to be an in-depth look at how WPF is different from WinForms or how to switch from WinForms to WPF, but is more of a brief summary on the change in mindset needed when moving from WinForms to WPF.

With WPF, your application consists of the objects you create, and you use DataTemplates and UI objects to tell WPF how to draw your application components. That’s the opposite of WinForms where you build your application out of UI objects, and then supply them with the data needed.

Once you grasp this key difference, WPF becomes much easier to understand and work with.


What is this “DataContext” you speak of?

July 14, 2012

I frequently see new WPF users confused about what the DataContext is, and how it is used. Hopefully, this can help clarify what the DataContext is, and how it is used.

What is the DataContext?

In WPF, there are two layers to an application: the UI layer and the Data layer.

The Data layer for an application starts out as null, and you can set it using the DataContext property. All UI objects will inherit their DataContext from their parent unless you specify otherwise.

When using the Model-View-ViewModel (MVVM) Design Pattern, the DataContext (Data Layer) is your application, while UI objects, like Buttons, Labels, DataGrids, and even Windows, are all just user-friendly items that allow a user to easily interact with the DataContext, which is your actual application and is typically comprised of ViewModels and Models.

How is it used

Whenever you do a basic binding in WPF, you are binding to the DataContext.

For example, when you write

<Label Name="myLabel" Content="{Binding Path=Name}" />

you are binding to myLabel.DataContext.Name, and not to myLabel.Name.

Other binding properties, such as ElementName or RelativeSource, can be used to tell the binding to lookup the property in something other than the current DataContext.

An Example

Lets start with a regular Window. Without setting the DataContext, the window still displays but there is no data behind it.

<Window x:Name="MyWindow" ...>
   ...
</Window>

Now suppose we set the DataContext to an object of type ClassA in the code-behind when this Window initializes:

public partial class MyWindow: Window
{
    public MyWindow()
    {
       InitializeComponent();
       this.DataContext = new ClassA();
    }
}

Now the data layer behind that the Window is an object of type ClassA.

If ClassA has a property called Name, I could add a Label to the window and bind it to Name property of the DataContext, and whatever value is stored in ClassA.Name would get displayed.

<Window x:Name="MyWindow" ...>
   <Label Content="{Binding Name}" />
</Window>

Now, suppose ClassA has a property called ClassB, and both classes have a property called Name. Here is a block of XAML which illustrates how the DataContext works. It also includes an example of how a control would refer to a property not in its own DataContext.

<!-- DataContext set to ClassA in initialization code -->
<Window x:Name="MyWindow"> 

    <!-- DataContext here is not specified, so it's inherited 
         from its parent's DataContext, which is ClassA -->
    <StackPanel> 

        <!-- DataContext inherited from parent, which is 
             ClassA, so this will display ClassA.Name -->
        <Label Content="{Binding Name}" />

         <!-- DataContext is still ClassA, however we are 
              setting it to ClassA.ClassB with a binding -->
        <StackPanel DataContext="{Binding ClassB}">

            <!-- DataContext inherited from parent, which is 
                 ClassB, so this will display ClassB.Name -->
            <Label Content="{Binding Name}" />

            <!-- DataContext is still ClassB, but we are 
                 binding to the Window's DataContext.Name, 
                 which is ClassA.Name -->
            <Label Content="{Binding 
                       ElementName=MyWindow, 
                       Path=DataContext.Name}" /> 
        </StackPanel>

        <!-- We've left the StackPanel with its DataContext 
             bound to ClassB, so this Label's DataContext 
             is ClassA (inherited from parent StackPanel), 
             and we are binding to ClassA.ClassB.Name -->
        <Label Content="{Binding ClassB.Name}" />
    </StackPanel>
</Window>

As you can see, all the basic bindings look for their value in the data layer (DataContext) of the UI object

Summary

So to summarize, WPF applications have two layers: the UI layer and the Data layer. The data layer for an application starts out as null, and can be set using the DataContext property. UI objects without a DataContext set will inherit their data layer from their parent object. Bindings are used to look up values in the data layer, and display them in the UI layer.

When using the MVVM design pattern, the data layer is your application, while the UI layer just provides a user-friendly way to access the Data layer.


Approaching another programmer about code-quality

July 2, 2012

This is another post I wrote for the Programmers.SE Blog a few months back. They’ve finally published the article, so I thought I’d include a copy of it on my own blog.


Programmers have to work with large amounts of bad code. Sometimes its your own code, but other times its another programmer’s code. If you have to frequently work with another programmer’s bad code, you will eventually wish to approach them about their code quality, however how to do this without causing offense or resentment is not always easy. This article is about the approach I would take when wanting to casually talk with another programmer about their code quality.

Determine the problem

First off, determine what exactly the problem is, and verify that it is worth bringing up. Ask yourself:

  • Do you work with this person on a regular basis?
  • Will you be working with, and maintaining their code in the future?
  • Is this an actual problem that harms productivity, performance, or security, or is it simply a case that your preferences are different from theirs? For example, simply complaining that “your naming convention doesn’t match mine” is not a very good reason, however saying “your naming convention makes it hard to understand what is going on in the code” is a much better.

If you answered yes to all of those, then it sounds like you might have a good reason to approach someone about their code quality.

Gather your arguments

Once you’ve determined there is a valid reason for trying to change the way another programmer does things, get your arguments prepared. Identify why the code is harmful to the development environment, and figure out the ideal way of coding it instead. Pick some code samples illustrating the problem, and write your own way of coding the same piece. Determine what your arguments are for why your code is better than the existing code sample. Don’t use arguments such as “it’s best practice”, but instead explain why it’s a best practice (readability, maintainability, reusability, etc)

Approaching the other programmer

Now that you know your arguments for why you think your code is better than theirs, and have a clear idea of what the ideal code should look like, arrange a time to talk with the other programmer.

This could be a casual conversation, or it could be setting up an appointment to talk with them about your concerns. How you choose to approach your co-worker is based on your level of comfort with them, the organization’s environment, and both of your ranks within the organization. For example, if I wanted to talk to the programmer next to me, I might simply ask them if I could have a moment of time whenever they’re available to talk with me about a piece of code, however if it’s my boss, I might send him/her an email asking if I could setup a brief meeting with them to discuss some code I’ve been working on.

Some people might argue that approaching a boss is different than approaching a co-worker, however I feel they are both people and both deserve equal respect. The only real difference I see is that your boss’s time is usually more valuable to the company, so be aware of that when talking with him/her.

What to say

When you actually talk with the other programmer, I usually find a good way to start the conversation is to ask them to explain their code. Ask if there was a reason for their style of coding, or tell them you’ve never seen something coded that way, and ask them why they chose that method. Really listen to what they have to say during their explanation. It could be that their way is right, and you are wrong, in which case take notes and learn from it!

If you still think the code is bad and worth changing, show the other programmer how you would code the same piece of code, and tell them why you would code it that way over his/her way (better performance, fewer chances of errors, easier for other programmers to read/maintain, etc).

Focus on why your method of coding is better, and not why their method is worse. Nobody likes being accused of writing bad code, although in reality we were all new once and I’m sure we’ve all written some horrendous code at some point in our lifetime. Be sure to keep the conversation focused on the code, and avoid turning it personal by talking about the person who wrote the code. It is always best if you can show that you understand that sometimes bad code gets written, whether it was due to time constraints, inexperience, or simply a bad day.

In addition, don’t try and get them to change their old code (unless you are their boss and want them to spend time doing so). Your goal is to educate them so they stop making the same mistake in the future, not berate them over past mistakes and punish them by extra work.

Afterwards, see if he/she still supports their coding style over yours. If they are open to improvement, they will likely change their way of coding going forwards. But if they still prefer to use their coding style, you are not likely to change their opinion, so drop the subject and don’t bring it up again unless their code is actually harmful.

Conclusion

Remember, nobody can write perfect code, and good programmers are always looking for improvement. The world of programming is so big that its impossible to know everything. It’s very likely that the other programmer doesn’t know there is a problem with their code, and would appreciate the input, providing you do it in such a way that you are teaching them, and not insulting them.

So don’t be afraid to approach another programmer about their code quality. I know I would appreciate the conversation, and I think you would too.


Help, I just graduated but I don’t feel like I know how to program!

May 12, 2012

There was a great question on Programmers about graduating with a programming degree, but not knowing how to program. I see this kind of question a lot, and I felt the same way when I first got my degree, so I thought I’d write about my experiences and what I learned when first started programming.

This was originally an article I wrote for the Programmers.SE blog, however the blog doesn’t appear to be happening at this time so I am posting it on my own blog instead.


Start with baby steps

First off, don’t expect to be able to code enterprise-level applications or the next Facebook right away. You really can’t become a good programmer without a lot of practice, so practice any way you can. This can include hobby projects, reading books or source code, or even answering questions on Stack Overflow.

The book Outliers: The Story of Success frequently states that to become a master in any field you need to practice it for a total of 10,000 hours. In case you don’t want to do the math, that’s about 3.5 years of programming 8 hours every single day. If you only program during business hours at work, that’s almost 5 years.

Don’t discount your education

Rachel - Graduation Picture
When I first started working, I felt my education was worthless; that it just taught me stuff that was never used in the workplace. I soon realized it provided me with something better than syntax: it provided me with a good foundation for programming. For example, it didn’t teach me design patterns, but it did teach me what design patterns were and how / when to use them. And I might not have built a data access layer in my class projects, but I knew what they were for and when to use them.

It also provided me with resources such as books, an online library, and networking contacts in the industry. In addition, it gave me a fancy piece of paper which can be very useful for getting your foot in the door when you don’t have experience.

Of course, it didn’t teach me everything. Looking back I wish I had been taught about things like Version Control and Unit Testing. But they did their best to provide me with a solid foundation to build upon in the short time I was there, providing I was willing to go out there and keep learning.

Always be learning

One of the first things I got taught in college was that to be an IT professional, you really need to be a life-long learner. You can’t just graduate and expect you’ll have everything you need to get a high-paying job for the rest of your life. You’ll need to be willing to spend the rest of your life learning new technologies and languages.

Whenever I come across something new, something I don’t understand, or something I’m not sure of how to do, I Google it. Most of the time I can find a simple definition or samples, and I can start from there. If I do start from samples, I hate just blindly copying/pasting. I always take the time to understand what the code does. It might be slower to start with, however once understood it makes me that much better of a programmer.

Remember, N years of experience means nothing if it was simply 1 year repeated N times. There are plenty of jobs out there that are that will let you accumulate years of experience without you ever needing to learn anything new, however I feel you simply cannot be a great programmer without continuing to learn.

Steps to success in programming projects

Here is a list of steps to success in any project as a new programmer:

  • Be positive when asked if you can do something.

    If someone asks you if you can do something, be positive in your response. Answering negatively, or even indecisively, will often result in a lost opportunity to learn and grow, so avoid that unless the task is truly outside the realm of possibility.

    I usually use terms like “I don’t see why not” or “shouldn’t be too hard”. You may not know how to do it right away, but you should have the tools (Google!) and intelligence needed to figure out how to get it done. I like to avoid actually saying “yes” unless I know I can actually do what is being asked.

  • Determine requirements.

    Sit down with your client (boss, customer, etc) and figure out what they want. I’m not going to go into details of gathering requirements here, but do take the time to draw out the screens they expect to see, and to determine the expected input / output. My favorite tool for screen mock-ups is Balsamiq (its free!).

  • Figure out how to build it.

    This is one of the most important steps. A huge part of programming (especially early on) is figuring out what your client wants, and then learning how to do that. Don’t just stick with your own knowledge base!

    For new programmers, I would suggest just focusing on just getting the desired results. Don’t get bogged down trying to learn design patterns, architecture, test-driven development, etc. Learn the basics of how to program first, then expand on that knowledge. And remember, keep it simple! You don’t need an enterprise-level solution for the FizzBuzz problem.

    At this point, if you determine that the project is completely out of your scope, say so. Even if you determine the project is far too large or complex for you to build, you will have at least increased your own knowledge, so I always see it as a win-win situation.

  • Build it.

    You might think this is the hardest step of all, but in reality it will eventually become one of the easiest ones. Gathering the requirements and figuring out how you’re going to build the application are much more important, and if done right, it will make this step a breeze.

    Of course, early on in your career this step will be the most time-consuming and frustrating one. It will likely consist of a lot of trial and error, but don’t be disheartened because this means you are learning! We learn much more from our mistakes than from our successes, and the more you learn, the better your programming skills will become.

Summary

So to summarize, don’t worry too much about not being able to build / understand enterprise-level applications straight out of college. Start small, and keep an always be willing to learn. Work on programming for results first, and worry about best-practices later on. Hobby projects are a great way to gain experience. And remember, don’t ever stop learning!


Validating Business Rules in MVVM

January 22, 2012

I’ve always thought that raw data validation should occur in the data Model, while Business Rule validation should occur in the ViewModel.

For example, verifying that a UserName is no longer than X length long should occur in the data model, while verifying that the UserName is unique would occur in the ViewModel. The reason for this is that the User Model is simply a raw data object. It doesn’t contain any advanced functionality like database connectivity, or knowing about other User objects. It’s a selfish little thing which only cares about it’s own data.

Since I use IDataErrorInfo for my validation and like to expose the entire Model to the View from my ViewModel, this presents a problem. Using the above example, I could bind a TextBox to SelectedUser.UserName, and it would automatically show an ErrorTemplate if the string was too long, however it wouldn’t show an error template if the UserName already exists.

After some thought, I decided to add a Validation Delegate to my Models to solve this problem. This is a delegate which ViewModels can use to add Business Logic Validation to its Models.

In the above example, the UsersViewModel might look like this:

public class UsersViewModel
{
    // Keeping these generic to reduce code here, but they
    // should be full properties with PropertyChange notification
    public ObservableCollection<UserModel> UserCollection { get; set; }
    public UserModel SelectedUser { get; set; }

    public UsersViewModel()
    {
        UserCollection = DAL.GetAllUsers();

        // Add the validation delegate to the UserModels
        foreach(var user in UserCollection)
            user.AddValidationDelegate(ValidateUser);
    }

    // User Validation Delegate to verify UserName is unique
    private string ValidateUser(object sender, string propertyName)
    {
        if (propertyName == "UserName")
        {
            var user = (UserModel)sender;
            var existingCount = UserCollection.Count(p => 
                p.UserName == user.UserName && p.Id != user.Id);

            if (existingCount > 0)
                return "This username has already been taken";
        }
        return null;
    }
}

The actual implementation of my IDataErrorInfo on my Model class would look like the code below. It’s generic, so I usually put it into some kind of base class for my Models.


    #region IDataErrorInfo & Validation Members
    
    #region Validation Delegate
    
    public delegate string ValidationDelegate(
        object sender, string propertyName);
    
    private List<ValidationDelegate> _validationDelegates = new List<ValidationDelegate>();
    
    public void AddValidationDelegate(ValidationDelegate func)
    {
        _validationDelegates.Add(func);
    }

    public void RemoveValidationDelegate(ValidationDelegate func)
    {
        if (_validationDelegates.Contains(func))
            _validationDelegates.Remove(func);
    }
    
    #endregion // Validation Delegate
    
    #region IDataErrorInfo for binding errors
    
    string IDataErrorInfo.Error { get { return null; } }
    
    string IDataErrorInfo.this[string propertyName]
    {
        get { return this.GetValidationError(propertyName); }
    }
    
    public string GetValidationError(string propertyName)
    {
        string s = null;

        foreach (var func in _validationDelegates)
        {
            s = func(this, propertyName);
            if (s != null)
                return s;
        }
    
        return s;
    }
    
    #endregion // IDataErrorInfo for binding errors
    
    #endregion // IDataErrorInfo & Validation Members

The idea is that your Models should only contain raw data, therefore they should only validate raw data. This can include validating things like maximum lengths, required fields, and allowed characters. Business Logic, which includes business rules, should be validated in the ViewModel, and by exposing a Validation Delegate that they can subscribe to, this can happen.


Navigation with MVVM

December 18, 2011

When I first started out with MVVM, I was lost about how you should navigate between pages. I’m a firm believer in using ViewModels to do everything (unless it’s View-specific code), and that the UI is simply a user-friendly interface for your ViewModels. I did not want to create a button on a page that has any kind of code-behind to switch pages, and I didn’t like the idea of my navigation being spread out throughout all the ViewModels.

I finally came to realize the solution was simple: I needed a ViewModel for the Application itself, which contained the application state, such as the CurrentPage.

Here is an example that builds on the Simple MVVM Example.

The ViewModel

Usually I name the ViewModel ApplicationViewModel or ShellViewModel, but you can call it whatever you want. It is the startup page of the application, and it is usually the only page or window object in my project.

It usually contains

    List<ViewModelBase> PageViewModels
    ViewModelBase CurrentPage
    ICommand ChangePageCommand

Here is an example ApplicationViewModel that I would use to go with the Simple MVVM Example.


    public class ApplicationViewModel : ObservableObject
    {
        #region Fields

        private ICommand _changePageCommand;

        private IPageViewModel _currentPageViewModel;
        private List<IPageViewModel> _pageViewModels;

        #endregion

        public ApplicationViewModel()
        {
            // Add available pages
            PageViewModels.Add(new HomeViewModel());
            PageViewModels.Add(new ProductsViewModel());

            // Set starting page
            CurrentPageViewModel = PageViewModels[0];
        }

        #region Properties / Commands

        public ICommand ChangePageCommand
        {
            get
            {
                if (_changePageCommand == null)
                {
                    _changePageCommand = new RelayCommand(
                        p => ChangeViewModel((IPageViewModel)p),
                        p => p is IPageViewModel);
                }

                return _changePageCommand;
            }
        }

        public List<IPageViewModel> PageViewModels
        {
            get
            {
                if (_pageViewModels == null)
                    _pageViewModels = new List<IPageViewModel>();

                return _pageViewModels;
            }
        }

        public IPageViewModel CurrentPageViewModel
        {
            get
            {
                return _currentPageViewModel;
            }
            set
            {
                if (_currentPageViewModel != value)
                {
                    _currentPageViewModel = value;
                    OnPropertyChanged("CurrentPageViewModel");
                }
            }
        }

        #endregion

        #region Methods

        private void ChangeViewModel(IPageViewModel viewModel)
        {
            if (!PageViewModels.Contains(viewModel))
                PageViewModels.Add(viewModel);

            CurrentPageViewModel = PageViewModels
                .FirstOrDefault(vm => vm == viewModel);
        }

        #endregion
    }

This won’t compile right away because I’ve made some changes to it. For one, all my PageViewModels now inherit from an IPageViewModel interface so they can have some common properties, such as a Name.

I also created a new HomeViewModel and HomeView since its hard to demonstrate navigation unless you have at least 2 pages. The HomeViewModel is a blank class that inherits from IPageViewModel, and the HomeView is just a blank UserControl.

In addition, I added an s to ProductsViewModel since it really deals with multiple products, not a single one.

An added advantage to having a ViewModel to control the application state is that it can also be used to handle other application-wide objects, such as Current User, or Error Messages.

The View

I also need an ApplicationView for my ApplicationViewModel. It needs to contain some kind of Navigation that shows the list of PageViewModels, and clicking on a PageViewModel should execute the ChangePage command.

It also needs to contain a control to display the CurrentPage property, and I usually use a ContentControl for that. This allows me to use DataTemplates to tell WPF how to draw each IPageViewModel.

<Window x:Class="SimpleMVVMExample.ApplicationView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:SimpleMVVMExample"
        Title="Simple MVVM Example" Height="350" Width="525">

    <Window.Resources>
        <DataTemplate DataType="{x:Type local:HomeViewModel}">
            <local:HomeView />
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:ProductsViewModel}">
            <local:ProductsView />
        </DataTemplate>
    </Window.Resources>

    <DockPanel>
        <Border DockPanel.Dock="Left" BorderBrush="Black" BorderThickness="0,0,1,0">
            <ItemsControl ItemsSource="{Binding PageViewModels}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Button Content="{Binding Name}"
                                Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                                CommandParameter="{Binding }"
                                Margin="2,5"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </Border>

        <ContentControl Content="{Binding CurrentPageViewModel}" />
    </DockPanel>
</Window>

In this example, I’m using an ItemsControl to display my PageViewModels. Each item is drawn using a Button, and the Button’s Command property is bound to the ChangePageCommand.

Since the Button’s DataContext is the PageViewModel, I used a RelativeSource binding to find the ChangePageCommand. I know that my Window is the ApplicationView, and it’s DataContext is the ApplicationViewModel, so this binding looks up the VisualTree for the Window tag, and gets bound to Window.DataContext.ChangePageCommand.

Also note that I am putting DataTemplates in Window.Resources to tell WPF how to draw each IPageViewModel. By default, if WPF encounters an object in it’s visual tree that it doesn’t know how to handle, it will draw it using a TextBlock containing the .ToString() method of the object. By defining a DataTemplate, I am telling WPF to use a specific template instead of defaulting to a TextBlock.

If you are continuing from the Simple MVVM Example, I moved the ProductView out of a ResourceDictionary and into a UserControl to make this simpler.

Starting the Example

The last thing to do is change App.xaml to make ApplicationView and ApplicationViewModel our startup, instead of ProductView/ProductViewModel.

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        ApplicationView app = new ApplicationView();
        ApplicationViewModel context = new ApplicationViewModel();
        app.DataContext = context;
        app.Show();
    }
}

Run the project and you should see something that looks like the images below, which quickly switches the CurrentPage when clicking on the Navigation buttons.

Screenshot of HomeHome

Screenshot of ProductsProducts

Summary

And there you have it. A simple navigation example with MVVM.

You can download the source code for this sample from here.

Once you get more comfortable with WPF, I would recommend looking into using a Messaging System, such as MVVM Light’s Messenger, or Microsoft Prism’s EventAggregator to broadcast ChangePage commands from any ViewModel so you wouldn’t need to find the ApplicationViewModel to execute the ChangePageCommand, however that’s for another day.

<< Back – A Simple MVVM Example
>> Next – Communication between ViewModels


Follow

Get every new post delivered to your Inbox.

Join 107 other followers