WPF Object Stretch – Alignment Properties vs Width/Height

designwpfxaml

In WPF's XAML, we can tell an element to fill its container like this:

<Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />

Why is it that when we set an element to Stretch, we do it via the HorizontalAlignment and VerticalAlignment properties? Why did the WPF design team decide to take this approach over having Width="Stretch" and Height="Stretch"? I presume it was a calculated decision, and I'm curious about the reasoning.

CSS, among other technologies, follows the convention that stretching is done via the width and height properties, and that alignment affects positioning exclusively. This seems intuitive enough: stretching the element is manipulating its width and height, after all! Using the corresponding alignment property to stretch an element seems counter-intuitive and unusual in comparison. This makes me think they didn't just pick this option for no reason: they made a calculated decision and had reasons behind it.

Width and Height use the double data type, which would ordinarily mean assigning it a string would be silly. However, WPF's Window objects can take Width="Auto", which gets treated as double.NaN. Couldn't Width="Stretch" be stored as double.PositiveInfinity or some other value?

Best Answer

Because double.NaN and double.PositiveInfinity already have very specific meanings. It's pretty bad practice to repurpose special values like that in a completely different context, where it would have significantly different meaning. Just because an element cannot be NaN or PositiveInfinity (or for that matter -1) units wide doesn't mean you should reuse that value arbitrarily to mean something else. Suppose you calculated the with of an element dynamically, NaN or PositiveInfinity would still represent a division by zero and means something is wrong with the calculation, not that element should stretch.

It's true that WPF allows you to specify Width="Auto" which gets stored internally as NaN, however I would argue that this is indeed bad design (or at least not very good design—at least "Auto" is indeed not a number), for the reasons listed above. I can't say why the WPF team chose to allow one special value, and not the other, except that perhaps it was simply the best option to keep their layout algorithms simple and flexible. NaN has the added benefit that any arithmetic operations performed on it remain NaN, while many operations on PositiveInfinity result in NaN. This may make NaN more suitable for storing special values than PostitiveInfinity.

A much better solution can found in GridLength structure, which represents discreet measurements and special values (such as * and auto) appropriately. The designers of WPF could have used a similar structure to represent the width / height of all framework elements, but that would likely have made most of even the most basic layout algorithms much more difficult.

Related Topic