Monday, April 02, 2007

WPF Part 2 - Long Live the Layout Manager!

So I am back noodling around with Windows Presentation Foundation (WPF) and again it takes me a little longer than expected to put together a basic page UI.

While building a page for data entry, I was again reminded of the importance of a Layout Manager. This thing is so important it should be should be called Layout King, Panel Emperor or even God-King of the Presentation. There are several elements which enforce the complex demands of the Layout King: StackPanel, WrapPanel, DockPanel and the ever mysterious Grid.

Each element specializes in complex layout behavior; there are others but these are the ones that I've encountered to date.

Until yesterday, I had used all but the Grid. But then again, my UI arrangements were pretty basic. I needed a navigation space and a content space. These were fulfilled nicely by putting DockPanel in charge of some subordinate TreeView and Frame elements.

Now, however, it was time to get work done. Yup, at the end of the day, I needed an easy system of entering data. This is a business application after all, you know. My preference is for some type of 'table' like structure of labels and input controls. You know, basic form data entry just like when you fill out those loan application forms. You start at the top and work your way to the bottom, before signing your name (save). This is Data Entry 101, nothing fancy here.

I needed to recreate that experience using WPF.

With Windows Forms, I would have just dragged and dropped UI elements on to a form and arranged to my liking. I wouldn't have had anything as cool as custom re-sizing based on the form size, but I would have had instant gratification on what it would look like and a certain expectation of its runtime behavior.

With ASP.NET, I would have arranged my UI in a table to make sure that everything was aligned appropriately. I actually like this approach the best so far, which is ironic as I have a certain dislike for limited 'richness of experience' with web applications. However, it does give me certain flexibility if the browser is resized, etc.. Not to mention, now I can apply CSS to all my pages and get some instant style, something I never achieved with Windows Forms.

With WPF, I tried several different tactics at first, which is why it took so long. The drag and drop method didn't work so well, but that's ok. I'm getting used to just typing in what I need. But, then I remembered, I needed to choose a Layout Manager and I needed to choose wisely. I started with trying to get away with a horizontal oriented StackPanel, but whoa, was it pretty basic. What happened when I got to the end of my surface area? My controls wrapped in the StackPanel were truncated.

Next up to bat was the WrapPanel, while this worked pretty well, I would essentially need to be able to create 'custom controls' to link a Label with another input control so as to get WrapPanel to see the two controls as one. Kind of like paying taxes.

Well, since HTML tables worked so well for my ASP.NET UI's, I thought I would try the WPF version: Grid. Grid is mysteriously arcane element that requires certain sacrifices. You can't try dragging and dropping with the Grid. To do so just invites its Wrath. I kept trying to interact with it through the VS designer and every thing I tried invited horribly cryptic Margin properties to be written everywhere in my XAML! Remembering to offer up sacrifices, I had worked my way up through chickens (as I am want to do) and was eyeing the neighbors goat when I communed with the Pagan Spirits that have gone before me ( a.k.a. Google'd) and located a couple of posts indicating that designer support is only half-baked and won't be fully available until the next release of Visual Studio ("Orcas").


Ignoring the designer completely, I jumped back into the IDE and crafted a Grid, with 2 columns and 2 rows. This is the master layout grid. In the screenshot, this has the 'pink' background.

Then I added another grid (0,0) with 6 columns and 4 rows. With a little creative use of the ColumnSpan property (hey! Just like ASP.NET!), I was able to get my 'form-based' input UI. This has the 'green' background.

Then adding some more UI elements at (0,1) inside a WrapPanel. These will need to be converted to Grid if anything complex needs to be added. This section is colored 'blue'.

Then finally, a space (1,0) for control elements such as 'Save'. Here is a basic StackPanel, horizontal orientation in the event I need to add more buttons/elements. This space is in 'yellow'.

Here is a reference shot with the different regions:





The final result looks something like this shot here.




This type of Grid-based approach to laying out controls is very similar to ASP.NET, so once I got going it was pretty straight forward. I did run into the occasional formatting issue (one or two of which seemed to 'self-resolve', which always makes me nervous).

I don't know if its the best approach to take, so I'll keep on the lookout for an alternative.


References

.NET and Funky Fresh - Rob Eisenberg