Being an Web developer kind of guy, one thing that I've always loved is markup. In fact, I've worked for the same manager at two different software companies in my lifetime where we developed software around Internet Explorer using a technique called
binary DHTML behaviors. (
Note: you can also create binary behaviors with VB6, which gives you the ability to use edit-and-continue during development!) One reason we really liked doing this is the ability to create a very rich UI with HTML. This is something that is very difficult to duplicate with Win32 forms either with MFC or VB. Additionally,
IE supports databinding with XML data islands to elements such as HTML tables. If you don't know what a binary behavior is, basically it let's you poke at the DOM using a compiled langauge instead of using JavaScript (HTCs) for example. The problem with binary behaviors is they are, of course, COM-based. Meaning, you end up with a distribution problem in some cases (it depends on the administrator's settings, etc). Although, when .NET first went RTM, we had an easier time rolling out a simple COM binary via a cab file than it would have been trying to get the .NET Framework installed on every desktop. Two "new" technologies that are dear to my heart because of my aforementioned experience, are
XAML and
smart clients.
I'm not going to discuss smart clients today, but what I am going to talk about is how much I appreciate the very extensive support for layout that WPF offers. This is driven from several things that I've read or have been reading lately. One of which is the Programming WPF book I recently purchased. Of course, the first thing I did after getting the book was dive right into the data binding chapter. But, I soon went back and was floored by the chapter on layout controls. For example, as Ian Griffiths and Chris Sells go into great detail about various WPF layout controls at your disposal, including one of the most powerful: the Grid. Let's say I want to make something similar to this HTML table:
<!-- Define the grid layout -->
<Grid ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<!-- Put stuff in the grid -->
<TextBlock Grid.Column="0" Grid.Row="0">Hello</TextBlock>
<TextBlock Grid.Column="1" Grid.Row="0">World</TextBlock>
<TextBlock Grid.Column="0" Grid.Row="1">Grid</TextBlock>
<TextBlock Grid.Column="1" Grid.Row="1">Example</TextBlock>
</Grid>
The Grid itself is somewhat exciting in terms of being able to layout UI elements, but there is something else that is far more interesting going on here. If you look at the TextBlock elements, you'll see that they contain Grid.Column and Grid.Row properties. Hopefully it is obvious what those property settings are doing, but how are they implemented? At first glance it might appear that there is some kind of magic parsing going on in Visual Studio or perhaps the TextBlock control provides code for a Grid.Column and Grid.Row property. This is not the case. A very interesting design feature in WPF is something called attached properties. The TextBlock control inherits (indirectly) from DependencyObject. Drew Marsh has a great post about this here. The Grid itself contains static, readonly fields of type DependencyProperty:
public static readonly DependencyProperty ColumnProperty;
public static readonly DependencyProperty ColumnSpanProperty;
public static readonly DependencyProperty IsSharedSizeScopeProperty;
public static readonly DependencyProperty RowProperty;
public static readonly DependencyProperty RowSpanProperty;
public static readonly DependencyProperty ShowGridLinesProperty;
What happens behind the scenes for the XAML TextBlock items is something close to the following.
TextBlock tb = new TextBlock();
tb.SetValue(Grid.ColumnProperty, 0);
tb.SetValue(Grid.RowProperty, 0);
tb.TextContent = "Hello";
The SetValue method is provided by the TextBlock object's base class DependencyObject. If you pop open reflector and start looking around, you'll see this is pretty amazing stuff to make this all happen (as you can read more about here).
public void SetValue(DependencyProperty dp, object value)
{
//magic stuff: get property metadata and set the value. :-)
}
One last note...Aside from the book he co-authored, another reason I started looking into how this stuff works is because of IanG's blog post about C# 3.0 Extension Methods which is definitely a related topic and a great read. One of my favorite quotes is...
I think my slightly negative reaction is similar to the feeling I first got when I saw non-member functions in C++ proposed as being better than member functions in certain scenarios. "But that's not OO," I spluttered in my (relatively) youthful idealism. These days I've learned to be suspicious of any practice whose sole justification is that it's "more object-oriented." If that's the only reason something has been done in a particular way, it's probably a code smell. OO is just a toolkit, and for certain jobs, other styles (e.g. functional programming) sometimes offer better tools. Of course, if being "more object-oriented" offers specific advantages in your scenario, then more power to you, but being OO should not be an end in itself. The fact is that not all methods belong in classes. You can see this from the way some classes are really nothing more than namespaces in disguise. (Take a look at System.Math for example.)