Tuesday, February 25, 2014

Re-using User Controls

I spent most of the afternoon chasing this one down. It's for WPF version 4.0.

The problem started when I published a WPF application using ClickOnce. On two out of the five computers that installed and tested the application the user was getting a "An Exception was thrown by the Target of the Invocation" error whenever they tried to load a particular page. The page is a UserControl that I instantiate and assign to a user control on the main page. The error did not indicate if the problem was in the user control being loaded or the code that was loading the user control.

The first thing I did was to write a utility function that recurses through the InnerExceptions and concatenates all the error messages together. Then it appends the stack trace. It looks like this...



VB.Net
Public Shared Function GetFullMessage(ByVal ex As Exception) As String Dim sMsg As String = ex.Message Do While ex.InnerException IsNot Nothing ex = ex.InnerException sMsg &= vbCrLf & ex.Message Loop sMsg &= vbCrLf & ex.StackTrace() Return sMsg End Function
C#.Net
public static string GetFullMessage(Exception ex) { string sMsg = ex.Message; while (ex.InnerException != null) { ex = ex.InnerException; sMsg += Constants.vbCrLf + ex.Message; } sMsg += Constants.vbCrLf + ex.StackTrace(); return sMsg; }

After utilizing this function and deploying a new version I got an error message that suggested that I was trying to create a control with two parents (not allowed) and it was line 1313 (unlucky for some) of the user control's XAML that was doing it. Line 1313 looked like this...

<UserControl Name="EditDocumentNotesUserControl" Content="{StaticResource DocumentNotes}"/>

And the DocumentNotes resource is defined as...

<local:DocumentNotes x:Key="DocumentNotes"/>

The XAML contained another line earlier that also referenced the same StaticResource. I was trying to use the same User Control twice on the same page so I had two references to the same StaticResource which would cause the UserControl defined in the StaticResource to have two parents. A control can only have one parent. As the XAML compiler parsed my XAML it threw an exception which resulted in the very unuseful error I saw. I have no idea why three other computers did not throw the error or why it works in the VS2010 development environment.

The solution, obviously, is to define two StaticResources and reference each of them once, like this...

<local:DocumentNotes x:Key="AddDocumentNotes"/>
<local:DocumentNotes x:Key="EditDocumentNotes"/>
.
.
.
<UserControl Name="AddDocumentNotesUserControl" Content="{StaticResource AddDocumentNotes}"/>
<UserControl Name="EditDocumentNotesUserControl" Content="{StaticResource EditDocumentNotes}"/>

No comments:

Post a Comment