February 10, 2010
Attached properties in Silverlight control templates
Attached properties in WPF and Silverlight are a handy way to associate extra information with a control, and a common way to use them in WPF is to create a control template which consumes the extra data via a template binding.
Unfortunately, if you do this in Silverlight, it gives you the White Screen of Death, and either no exception at all or the infamous "Error HRESULT E_FAIL has been returned from a call to a COM component” which is like getting no exception at all except more irritating. Here’s a simple repro case:
<UserControl x:Class="SilverlightFail.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SilverlightFail">
<UserControl.Resources>
<Style x:Key="Testy" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="4" Background="HotPink">
<TextBlock Text="{Binding (local:Test.TestString),
RelativeSource={RelativeSource TemplatedParent}}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<StackPanel x:Name="LayoutRoot">
<TextBlock Text="Button to follow" />
<Button local:Test.TestString="Fie!" Style="{StaticResource Testy}" />
</StackPanel>
</UserControl>
Here we’ve defined a custom Button style which simply renders the attached Test.TestString property in a pink box. Run this sample (with the obvious attached property definition) and you get the White Screen of Death. You may get the COM exception – I get the exception on my home machine but nothing on my work machine, so this may be a 32/64-bit issue, I don’t know. But what you don’t get is a the word “Fie!” rendered on glorious HotPink. You don’t even get the “Button to follow” text, proving that it’s not just the button failing to render: the entire application has been taken down.
The problem is that, for some reason, Silverlight has forgotten about the local: XML namespace by the time it gets to the control template, and needs to be reminded. So you can work around the problem by redeclaring the attached property namespace on the root element of the template.
Unfortunately, it’s not quite as simple as that. If you just replicate the xmlns declaration from the root:
<Border CornerRadius="4" Background="HotPink"
xmlns:local="clr-namespace:SilverlightFail">
then you still get the White Screen of Death, though if your system gets exceptions then you’ll now get a helpful ArgumentException albeit with the less helpful message “Cannot resolve attached DependencyProperty local:Test.TestString in (local:Test.TestString).”
The trick is that you also need to explicitly specify the assembly, which you don’t normally have to do for the current assembly:
<Border CornerRadius="4" Background="HotPink"
xmlns:local="clr-namespace:SilverlightFail;assembly=SilverlightFail">
<TextBlock Text="{Binding (local:Test.TestString),
RelativeSource={RelativeSource TemplatedParent}}" />
</Border>
With this extra assistance Silverlight is finally able to resolve the attached property and your application reappears at last.
In related news, the beatings will continue until morale improves.
February 10, 2010 in Software | Permalink | Comments (0) | TrackBack
January 20, 2010
Wellington .NET User Group – Dive into LINQ
Thanks to everyone who came along to tonight’s LINQ refresher session. Nice to see the interest in the Reactive Extensions – maybe a future topic once I’ve got my head around them a bit more. (A lot more.)
In the meantime, here are the slides and demos. The zip file for the demos includes the Rx libraries, so the sample should run standalone; if not, or if you just want to learn more, you can get the Rx download from here.
January 20, 2010 in Software | Permalink | Comments (0) | TrackBack
January 12, 2010
XamlParseException debugging tips
Debugging declarative languages is a pain in the backside, but tools are beginning to emerge. Regular expression visualisers are becoming the new blogging engines (which were, in their time, the new e-commerce stores). CSS, once my bete noire, now has thingies that tell me exactly which style is causing my finely crufted werds to be squeezed into a column two pixels wide and displayed so far outside the page boundary that they need their own postcode, and can finally be downgraded to a bete grise. And WPF has… the XamlParseException.
Here, then, are a few basic tips for debugging XamlParseExceptions.
0. Don’t just dismiss the exception notification. It contains vital clues.
This may seem obvious. But a lot of developers have been trained by procedural exceptions to get the exception assistant out of the way pronto and start waggling their mice over every variable in sight like a cat owner desperately trying to coax signs of enthusiasm from their frankly contemptuous pet.
Don’t do it. The debugger can’t help you here; the exception info is your lifeline. A XamlParseException usually contains three useful pieces of information: an inner exception (or lack of one), a location (which may be wrong, but can still provide clues) and a message. These will usually be enough to diagnose and fix the problem, if you take the time to read them.
1. Look at the inner exception. A XamlParseException does not necessarily mean there is anything wrong with your XAML.
This may seem counterintuitive. Heck, it is counterintuitive. But any unhandled exception in your window (or control) constructor will result in a XamlParseException.
How will you know whether it’s a XAML error or a constructor exception? Look at the inner exception. If there is one, and it’s a TargetInvocationException, then your constructor threw an exception. The TargetInvocationException has its own inner exception, which tells you the real underlying exception. Once you’ve got this, you’re back into the familiar realms of procedural debugging.
Here’s an unlucky fellow on Stack Overflow, getting a XamlParseException from some perfectly unexceptionable XAML. Take a look at that monster exception dump. There are two things right at the top of the message that indicate that this is a constructor exception rather than anything wrong with his XAML. First, the message is “Exception has been thrown by the target of an invocation.” That’s the spoor of TargetInvocationException. Start drilling. Second, the position is “LineNumber=1 LinePosition=9.” That’s right on the x:Class attribute. This means there’s a problem hooking the XAML up to the class: unless the class is complete garbage, that again suggests a constructor problem. Sure enough, wading through the trail of inner exceptions we find a configuration exception with a nice simple stack trace pointing very clearly to the culprit. Problem solved.
2. Beware of loose content. Sometimes the exception points to the element after the error.
XML is a finicky language, and combined with the strict content models of WPF this makes it easy to introduce errors through simple typos. One error I’ve run into a fair few times is when you accidentally leave a bit of loose content lying around:
<StackPanel Margin="20">>
<TextBlock Text="One" />
<TextBlock Text="Two" />
</StackPanel>
This compiles, but blows up at runtime. The exception assistant confidently locates the error on the first TextBlock element. You might be tempted to roll up your sleeves and start hacking on that TextBlock until it jolly well parses. But remember: stop, wait, look at the exception:
'String' object cannot be added to 'StackPanel'.
Well, hang on. A TextBlock isn’t a string. Can we see any direct descendants of the StackPanel that are strings?
On closer examination, a bit of sloppy editing – assisted by Intellisense, the world’s leading producer of loose content – has left a stray > after the StackPanel declaration – and immediately before the TextBlock that the exception message was directing us to.
Loose content can be a bit hard to spot, and the bad location pointer doesn’t help. If you’ve got an exception message complaining about strings but pointing to an element, try looking backward from the exception location and see if you can spy a spurious character or two.
3. Check your spelling… and capitalisation.
XAML is case-sensitive and, in a shock new development for programming languages, typo-sensitive. If you create a resource with the key “MyResource” and then refer to it using “{StaticResource myresource}” or “{StaticResource MyResuorce},” then the compiler will cheerfully assume that these res0urces will be delivered by magic pixies at some later stage. Needless to say, come runtime, the magic pixies are still down the pub, and you’re left with the inevitable XamlParseException.
Once again, the clue is in the exception message. The exception will tell you which resource reference it couldn’t resolve, and where to find that resource reference. (For once, the location is generally both accurate and useful.) If you read the exception message, all that remains is to curse your semi-literate and case-insensitive co-workers, and go figure out what the resource is meant to be called. This will involve trawling through 60000 lines of XAML spread across 48 merged resource dictionaries, trying to guess how your outsourced development team have managed to misspell “burhs.” Simple solutions to this one are left as an exercise for the reader.
This isn’t by any means a comprehensive guide to the wonderful world of the XamlParseException. In particular, Silverlight programmers can expect to enjoy numerous other adventures in— no, only kidding. Silverlight programmers will continue to get AG_E_UNKNOWN_ERROR for any and every problem. And if anyone knows how to debug that, I’d love to know the secret.
January 12, 2010 in Software | Permalink | Comments (4) | TrackBack
October 31, 2009
Units of measure in F#
The latest version of F# introduces units of measure. Using this feature, you can indicate that a numeric value is in a particular unit – metres, seconds, etc. – and the compiler will track that as part of the data type and validate that units are being converted and compared correctly.
For example, we can declare the following values:
let distance = 1000.0<m>
let time = 400.0<s>
Give these the ol’ Intellisense mouse waggle, and you find that distance has type float<m>, and time has type float<s>. Try to add them together, and you get a tasty compiler error:
let nonsense = distance + time
FS0043: The unit of measure 's' does not match the unit of measure 'm'
But divide them and the compiler recognises that it makes sense, and figures out and tracks the derived unit of measure:
let speed = distance / time
speed has type float<m/s>, and again the compiler enforces that operations on speed are compatibly typed:
let description =
if speed > 10.0<m s^-1> then
"fast"
else
"slow"
Notice that F# supports the Proper Science notation of negative exponents as well as the Way Everybody Really Does It of division notation.
Derived units of measure can have names: the type float<kg m s^-2> is the same as float<N> and values of these types are therefore compatible.
let mass = 1.0<kg>
let accel = 50.0<m/s^2>
let whompiness = mass * accel
let ouch = whompiness > 100.0<N> // compiles
Where do units of measure come from? Well, when a daddy unit of measure and a mommy unit of measure love each other very much… but we’ve already talked about derived units of measure. In fact, there are no units of measure built into the F# language or core library. So either you have to define the units you need using the MeasureAttribute:
[<Measure>] type m
or you can import a bunch of standard SI units (basic units like the metre, kilogram and second, and derived units like newtons) from the F# Power Pack DLL:
// after referencing FSharp.PowerPack.dll
open Microsoft.FSharp.Math.SI
The Power Pack also includes a bunch of physical constants:
open Microsoft.FSharp.Math
let description =
if speed < PhysicalConstants.c then
"it's science"
else
"it's science... fiction!"
Naturally, these are all declared with the correct units of measure so efforts to compare Planck’s constant to the speed of light will meet with ignominious failure. To work around this, tell your boss you need $370bn for a new particle accelerator.
To be clear, F# doesn’t assign any actual semantics to units. For example, if you declare imperial units (because if it was good enough for the Babbage Engine, it’s good enough for the CLR, by Jove):
[<Measure>] type ft
F# won’t let you combine feet with metres. It has no way of knowing that ft is a length measure, or how it would convert to metres. However you can of course create conversion functions for your units:
let feetToMetres(f : float<ft>) =
f * 0.3048<m> / 1.0<ft>
let totalLength =
100.0<m> + feetToMetres(100.0<ft>)
Notice that our metres-per-foot expression spells out 1.0<ft> rather than 1<ft>. F# only allows units of measure to be applied to floating point values, not integers.
Finally, be aware that units of measure are erased during compilation. At runtime, F# (or rather the CLR) sees only plain old floats. Unit checking is part of the compile phase only.
October 31, 2009 in Software | Permalink | Comments (2) | TrackBack
September 15, 2009
Code Camp Auckland - .NET languages talk
Thanks to everyone who came to the Auckland Code Camp, to all the speakers and especially to the hard-working organisers! Here are the slides from the .NET languages talk:
What's happening in .NET languages - slides (PPTX format)
The demos were basically pretty closely derived from the Expert F# book and can be got from the book's Web site.
September 15, 2009 in Software | Permalink | Comments (0) | TrackBack
TechEd 09 - Visualising data in Silverlight and WPF
Thanks to everyone who came along to the Silverlight and WPF session yesterday. Unfortunately the final demos got a bit rushed but here's the complete code to all the samples which I hope will make a bit more sense when taken with a bit more leisure!
Visualising Data in Silverlight and WPF - slides (PPTX format)
Visualising Data in Silverlight and WPF - demos
September 15, 2009 in Software | Permalink | Comments (0) | TrackBack
September 02, 2009
The case of the missing custom attributes
If you’ve used .NET a lot, you probably haven’t come across the Attribute.TypeId property. This is the key – quite literally – to a problem that doesn’t come up very often – and by “not very often” I mean today I came across it for the second time in eight years – but should never have come up at all and is quite baffling when it does.
Let’s review. .NET allows you to define your own attributes. These attributes can be applied to types, methods, properties, and so on. You can get at these attributes using reflection. Life, in short, is good, at least for people whose desires extend no further than defining custom attributes and retrieving them again.
But .NET also has a sort of shadow type system: an early, hulking kind of dynamic type system tacked onto the side of the .NET 1.0 static type system. It dwells in the System.ComponentModel namespace, TypeDescriptor is its herald, and ICustomTypeDescriptor is its tyrant king (and TypeConverter its capering fool). The purpose of the shadow type system is to allow types to “adjust the truth,” adding properties that they don’t really have but are prepared to fake, and removing properties that they don’t want to talk about. This is jolly useful. It’s what supports, for example, making a Tooltip property appear in the Windows Forms property grid even though no control class actually has a Tooltip property, or applying Dynamic Data attributes to a property in one class by applying them to a field in a completely different class.
For 99.9% of the time – or, to be more exact, for 2920 days out of 2922 – the shadow type system works okay. However, it does have some surprises up its sleeve, and one of those relates to custom attributes. Specifically, if you apply more than one instance of the same custom attribute to a member, the shadow type system will randomly pick one of the instances, and throw the other one away.
Here’s an example. Suppose we define a LocalDisplayNameAttribute class, which can be applied to a property to define a localised display name for a given culture:
[LocalDisplayName(“en-NZ”, “Sweet as”)]
[LocalDisplayName(“en-UK”, “Jolly good, old bean”)]
[LocalDisplayName(“en-US”, “WOO! YOU ROCK!”)]
public bool Yes { get; set; }
And now we ask the shadow type system for these attributes:
var prop = TypeDescriptor.GetProperties(type, “Huzzah”)[0];
var ldns = prop.Attributes.OfType<LocalDisplayNameAttribute>;
Console.WriteLine(ldns.Count());
This prints 1 rather than 3. All instances of LocalDisplayNameAttribute except one have been discarded.
And this is where Attribute.TypeId comes in.
Attribute.TypeId has nothing to do with types, and very little to do with IDs. It is misleadingly named, and misleadingly implemented. Attribute.TypeId’s actual job is to answer the question, “Is this attribute instance a duplicate of this other attribute instance?”
Now the real type system has no problem with duplicate attribute instances. It just stores the attributes and serves them up on demand, without passing judgment. Hey, you wanted duplicates, you can have ’em.
The shadow type system, on the other hand, hates duplicates and makes sure to remove them during its process of “adjusting the truth.” And it uses the TypeId as the criterion for doing so. (Specifically, it uses TypeId as a dictionary key.) And – and this is the kicker – the default implementation for TypeId is to return the attribute type. Consequently, by default, the shadow type system sees all instances of the same attribute type as duplicates to be winnowed down to one. In the example above, the shadow type system decided that the three LocalDisplayNameAttribute instances were duplicates and threw out all but one.
So, finally, we come to the fix.
If you’re creating a custom attribute which allows multiple applications, you almost certainly want to override TypeId to return a unique value for each attribute instance. This could be a smart implementation which returns some appropriate combination of the attribute data, or it could just return a new GUID or even a this reference.
In the LocalDisplayNameAttribute example, as far as we’re concerned, there should be only one instance per culture ID. If someone insists on supplying multiple local display names for the same culture:
[LocalDisplayName(“en-NZ”, “Sweet as”)]
[LocalDisplayName(“en-NZ”, “Choice”)]
then it’s choice and sweet as that the shadow type system recognises these as duplicates and dedupes them for us. But we don’t want these en-NZ display names to come up as duplicates of other culture’s names and cause them to be discarded. So our override of Attribute.TypeId looks like this:
public override object TypeId {
get { return _cultureId; }
}
Parturient montes, nascetur ridiculus mus. Well, better an easy fix than a hard one.
So what do you need to remember?
First, TypeId doesn’t identify a type. It doesn’t really identify anything. It answers the question, “are these two attribute instances duplicates?”
Second, if you’re seeing custom attributes go missing, TypeId is probably the source of the problem.
Third, and consequently, if you’re writing a custom attribute, and it allows multiple instances, you’ll probably want to override TypeId.
You won’t see this very often. Unfortunately, when you do, the documentation is almost completely useless, and the default behaviour is more than a little surprising. So file it away. In 2013, you might just need it.
September 2, 2009 in Software | Permalink | Comments (3) | TrackBack
August 31, 2009
Code Camp Auckland 2009
The now traditional pre-TechEd Auckland Code Camp will be happening on 13 September. In addition to the usual developer festivities there’ll be a SQL Server track, and a security workshop led by the mighty Michael Howard, which should be pretty awesome. And as always it will be free to attend.
August 31, 2009 in Software | Permalink | Comments (0) | TrackBack
August 30, 2009
Those years in marketing taught me nothing
Darryl is running a competition: “If you were talking to an Oracle DBA what would be the top five features of SQL Server that you’d point out to them that makes SQL Server compelling?”
This was my reaction:
If I were talking to an Oracle DBA, the five compelling features I would point out would be ease of use, ease of use, ease of use, ease of use and ease of use.
The Oracle DBA would then roll his eyes, sigh condescendingly and reply, “You see, what you don’t understand is that Oracle isn’t a toy database.”
I would then punch him in the mouth, yell “Not so fucking smug now, are you, you fucker?” and then run away.
This is why I will never win any of Darryl’s competitions.
(In the interests of fairness I should note that this is exactly how Access users perceive software developers, so we have a few planks to take out of our own eyes too.)
August 30, 2009 in Software, Usability | Permalink | Comments (7) | TrackBack
June 10, 2009
Wellington Code Camp – this weekend
It’s been three years since the last (and indeed first) Code Camp in Wellington, so it’s about time we had another one, before the Christchurch guys left us for dust – and now it’s nearly here. So if you haven’t already signed up, and you’re up for a weekend of software architecture, .NET technology and being cut up in the pit lane by the demon Jeremy Boyd, register here and come along.
The schedule’s on the site, and I reckon it’s going to be an interesting mix of technology how-tos and broader architectural and structural talks. We’ve unintentionally ended up with several talks that ask people to take a second look at the way they “naturally” do things, which I think will make for plenty of great discussion and hopefully the occasional “aha!” moment.
Finally, since Mash gets disappointed if I write for too long in plain English, I’d just like to mention asynchronous monads. Thank you and good night.
June 10, 2009 in Software | Permalink | Comments (0) | TrackBack