WPF Debugging -- "Unable to cast object of type 'System.Windows.Controls.Grid' to type 'System.Windows.Window'
I hunted down a kind of a tricky error message today, and thought I'd write a quick post about it.
The Scenario:
I was doing some refactoring of a WPF app, encapsulating a section of one large-ish UserControl into a second UserControl.
- Prior to the refactoring, the single combined UserControl was running directly as the StartupURI of a test harness app.xaml, which resulted in it being hosted in a NavigationWindow when run
- The new extracted User Control contained most of the business functionality of the containing control
- The original UserControl was converted into a Window, containing a Grid, which then contained the extracted UserControl
The Error:
In the designer and at runtime, the following dialog popped up one time:
As soon as the dialog was cleared, both the designer surface and the app worked as expected.
The Solution:
It turns out that I had two lines in the constructor of my original user control (for positioning of the hosting window), which I had moved to the constructor in the extracted UserControl, which referenced the parent cast as a Window:
((Window)Parent.Left = 0; ((Window)Parent).Top = 0;
Obvious -- the Designer and WPF at runtime both evaluated this code, and since the parent was no longer a Window, the cast didn't work.
I moved these lines into the constructor and this resolved the issue.
Summary:
I'm not surprised that the error was thrown, but I was interested in two aspects:
- The Designer (Cider) evaluated the constructor code in the UserControl to the point that it threw casting errors on the Parent property. I guess this is necessary to make sure everything renders correctly in the Designer surface, but I shudder to think of the amount of logic that Visual Studio must run to decide what code to run and what to ignore when loading up the Designer surface.
- At runtime, WPF handled this error and generated its own error dialog, rather than throwing an unhandled exception. This would've been a lot easier to debug if it had thrown like a normal unhandled exception in Visual Studio.
All in all, it was an interesting exercise.