Implement screen layout by using nested control hierarchies
May include but is not limited to: using panel-derived controls, attaching properties
OK, as I promised, let’s get into the WPF business. As you may already know, WPF is a revolutionary UI system. It is revolutionary, because it breaks up with the messy, evil, sluggish, hellish, whatever bad property you can invent here, way of handling the screen real estate (you know, win32 and GDI+), and takes it to a new level where you can create a localization friendly UI which supports all possible screen sizes equally well, just by thinking of it, with the sacred milcore.dll.
OK, I hope you spot the irony up there. But WPF is in fact revolutionary in handling UI rendering and a lot of things, but it isn’t that easy. Especially if you are, like me, the guy who drags some controls into a form, and call that a UI. You can of course drag controls in the designer to a form, but surprisingly, that does the things WPF was made to fight with: hard-coding coordinates (OK, the coordinates won’t get hard coded, but their margin property will), so forgot the crappy designer built into VS and write XAML by hand, like real coders do! (Irony +1).
Since this is my first post about WPF, I think that this is the appropriate place to introduce the concept of XAML. XAML (as the name shows it clearly) is an XML-based language, and the full name of it is eXtensible Application Markup Language. Yes, it’s similar to building a web site. When you write some XAML code, and attach some event handlers to it, where you define the working of your application (sticking close to the Smart UI anti-pattern), and then try to run your application an interesting thing happens (I didn’t know it, so I write it here). Due to the magic of partial classes, your XAML markup and the code-behind file will be merged to one class! Fantastic, isn’t it?
But back to the topic and the exam itself. This section measures your knowledge in using panel-derived controls. In WPF, all the layout controllers inherit from the Panel class. To be more specific, the System.Windows.Controls.Panel, which in turn inherits from a bunch of classes. The Panel class ha three public properties you can use and these are:
- Background: taking a Brush to paint the background of your panel.
- Children: use it to iterate through all items stored in the panel.
- IsItemsHost: indicates whether or not the panel is used to show the items of an ItemsControl (I don’t understand this at this point, too).
This is a fair start; let’s see what are the controls inheriting from panel:
- StackPanel: this one is easy as pie: it aligns elements in a horizontal or a vertical stack.
- WrapPanel: a bit more sophisticated, it renders content as a series of wrapped lines, either horizontally or vertically.
- DockaPanel: yeah, this one has docking functionality. Of course for the four edges.
- Grid: this will be your favorite, it allows for highly sophisticated layouts.
- UniformGrid: imagine a grid with perfectly equal cells – that’s a UniformGrid.
- Canvas: the evil, coordinate based miscreation in WPF. Although very useful for creating games.
But layout containers can do only the first half of the work – controls hosted in them have their opinions about how to be set up, too. In fact, layout containers iterate over their children, and ask them how they’d like to be rendered (size, etc.). If the child can provide a reasonable answer, the container would respect that. Here are the properties you can use to fine-tune orientation, alignment and etc. on the child level:
- HorizontalAlignment: determines how to position the child when there’s extra space. The values are Left, Right, Stretch and Center.
- Verticallignment: the same as the previous, but of course vertically.
- Margin: adds margin outside the element. Basically has the same effect as the corresponding CSS property.
- MinWidth, MaxHeight and in between: I think that you can figure this out yourself. Beware – controls are cropped to fit!
- Width and Height: the pure evil, the explicitly set sizes. Only be used if between the appropriate min. and max. values. And overrides stretch! Oh, and one last thing. The best way to know the size of a control is to get it’s ActualWidth property. This will show you the actual width of your control, not just some handled value at the beginning of compilation!