WPF: Inheriting from custom class instead of Window

In ASP.NET, we learned that it is often interesting to inherit from another class than from System.Web.UI.Page. This allows to define common methods, such as utilities, etc... which are used by a set of web pages throughout an application.
In WPF, it's also possible to do the same, and to inherit from a custom class instead of System.Windows.Window, of System.Windows.Controls.Page, or of System.Windows.Controls.UserControl for example.
When you add a Window (or Page, or UserControl...) to a WPF project, the chain of inheritance is as follows:
Simple inheritance
If you have a special method "doSomething()" which you want to reuse in every Window in the application, then you can store it in an abstract class GalaSoftLb.Wpf.WindowBase and modify the inheritance as follows:
Custom inheritance
In the diagrams above, the Window class is the framework's one, and the class GalaSoftLb.Wpf.WindowBase is abstract.
In order to get the new Windows to derive from this abstract class, not only the C# code must be modified, but also the XAML code. This is a little tricky, because a special syntax must be used. Instead of the usual:
<Window x:Class="WindowsApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WindowsApplication1" Height="300" Width="300" > <Grid> </Grid> </Window>
We have instead:
<src:WindowBase x:Class="WindowsApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:src="clr-namespace:GalaSoftLb.Wpf" Title="WindowsApplication1" Height="300" Width="300" > <Grid> </Grid> </src:WindowBase>
Instead of deriving from Window, we derive from WindowBase. However, WindowBase is in an unknown namespace, so we must tell the XAML parser where to look for this class. This is done using the "xmlns:src" line. "xmlns" is for "xml namespace". "src" is a prefix, you are free to choose any qualifier you want. Typically, we use "src" for source, or "clr" for common language runtime, but this is up to you. It must be unique in this XML document.
Instead of specifying a URL like we normally do in XML, we use the syntax "clr-namespace" to define the src namespace. This means that the XAML parser will look into the Common Language Runtime, and look into a namespace named GalaSoftLb.Wpf to find the class WindowBase.
Note: The XML namespace and the CLR namespace are two different notions, we are at the crossroad of two worlds here. It's important to understand what these two namespaces represent.
Often, the base class is stored in an external class library, in order to reuse it in different WPF applications. In this case, the syntax becomes:
<src:WindowBase x:Class="WindowsApplication2.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:src="clr-namespace:GalaSoftLb.Wpf;assembly=GalaSoftLb.Wpf" Title="WindowsApplication2" Height="300" Width="300" >
Here, we tell the XAML parser to look for the namespace GalaSoftLb.Wpf into the DLL GalaSoftLb.Wpf.DLL, which must be referenced in the project.
In the code behind, there are no surprises:
public partial class Window1 : GalaSoftLb.Wpf.WindowBase
Finally a note about the implementation: If you want to store the abstract WindowBase class in a class library, you must add the following .NET libraries to the list of References: PresentationFramework, PresentationCore, WindowsBase.
Print | posted on Friday, March 2, 2007 10:20 AM

Feedback

# re: WPF: Inheriting from custom class instead of Window

left by Ini at 6/14/2007 3:47 AM Gravatar
Thanks for this great article. Very useful.

Can't view the form in Design mode after implementing a custom class. (VS 2005 with .NET 3.0 extensions)

Getting the following error message:

Window must be the root of the tree. Cannot add Window as a child of Visual.

Am I missing anything?

Thanks,
I.

# re: WPF: Inheriting from custom class instead of Window

left by Nino at 7/2/2007 8:53 PM Gravatar
Thanks for the hint, it helped me a lot.
Just to point to the problem I had:
I was unable to inherit my custom window defined in the application itself until I've successfully built the application with the custom class, and then inherit it.

# re: WPF: Inheriting from custom class instead of Window

left by Lori at 7/11/2007 11:35 AM Gravatar
I'm basically doing the same thing. I've retrofitted a Window to derive from a "WindowBase" class so that I can reuse some public properties and methods. When I run, I receive no errors, but I get a black screen. Do you have any pointers?

# re: WPF: Inheriting from custom class instead of Window

left by Laurent at 7/11/2007 7:22 PM Gravatar
Unfortunately, without more details, it's impossible to tell you why this happens. Try to make the simplest possible repro of that problem, zip all the files and send them to me, I will look into it. Have some patience though, as I am leaving for 2 weeks holidays soon.

Greetings,
Laurent

# re: WPF: Inheriting from custom class instead of Window

left by Emmanuel Huna at 7/18/2007 7:04 AM Gravatar
I followed your example but I get:

'TestInherit.WindowBase' cannot be the root of a XAML file because it was defined using XAML. Line 2 Position 5.

I have one window named "WindowBase.xaml" with a property named "TestProperty".

I have another window named "WindowDerived.xaml" where I changed the XAML to:

<src:WindowBase xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:TestInherit"
x:Class="WindowDerived"
Title="TestInherit" Height="407" Width="300"
>
<Grid>
</Grid>
</src:WindowBase>

Any ideas why I'm getting this error?

# re: WPF: Inheriting from custom class instead of Window

left by Laurent at 7/28/2007 3:21 AM Gravatar
Hi,

I am not sure what went wrong, but I am also not sure what exactly you're doing. Same proposal as with the previous poster, send me a zip with your code and I'll look at it.

Greetings,
Laurent

# re: WPF: Inheriting from custom class instead of Window

left by Bruce Philp at 9/16/2007 3:37 AM Gravatar
Hi,

I have tried following your example, but get the same error in "cannot be the root of a XAML file because it was defined using XAML".

Is there any chance you could send the example so that i can see what i cam doing or make the code available?

Many Thanks,
Bruce Philp

# re: WPF: Inheriting from custom class instead of Window

left by Ed Noepel at 10/2/2007 5:46 AM Gravatar
I would love to see the code as well. From my experience, you cannot subclass one element defined with XAML from another.

# re: WPF: Inheriting from custom class instead of Window

left by Laurent at 10/2/2007 9:21 AM Gravatar
Ed, I sent you a code example. I am not sure what you mean with "one element defined with XAML from another." In the example here, the class WindowBase does not contain XAML, it's just a class deriving from System.Windows.Window.

Note also that if the WindowBase class is abstract, Blend cannot handle it, so it's better to make it non-abstract.

Hope that clarifies things,
Laurent

# re: WPF: Inheriting from custom class instead of Window

left by Ed Noepel at 10/2/2007 2:29 PM Gravatar
I just felt it was important you mention the base window is not a "normal" WPF window defined using XAML with a code-behind. If it was, you would get the "cannot be the root of a XAML file because it was defined using XAML" compile-time error when trying to subclass it.

IMHO, this is a shortcoming of WPF. The workaround I am currently using involves moving all the XAML from the base window into a ControlTemplate and storing it in a ResourceDictionary. With this workaround, binding UIElement events in the template to handlers in the base window code is a bit obtuse. But it works.

# re: WPF: Inheriting from custom class instead of Window

left by Laurent at 10/2/2007 7:37 PM Gravatar
Ed,

If I understand your comment correctly, what you are trying to do is one of the big no-nos in WPF: Subclassing XAML markup. The regretted Kevin Moore (no, he didn't pass away, he just left Microsoft ;) has a post about this:

http://work.j832.com/2007/06/don-subclass-panel-unless-you-making.html

I think that you'll find in this post the answers to your problem.

The WindowBase in my example is a "normal" WPF window. In fact, when you define a Window (or any other UI element) in XAML, you actually just write the serialized version of this CLR object (XAML is a serialization language, not just a UI markup language). The only "shortcoming" of WPF (if you really want to name it so) is that you should not use subclassing to create a predefined look and feel for your UI elements. In fact, this is what User Controls are for, so I encourage you to use them to do what you want to achieve.

If I misunderstood your point, forgive me :-)

Greetings,
Laurent

# re: WPF: Inheriting from custom class instead of Window

left by Jonathan at 10/3/2007 5:36 AM Gravatar
When I try this, I get errors:
Partial declarations of 'InfinID.UI.Win.MyTest' must not specify different base classes

Apparantly there is a code generated .g.cs version of my class created that is inheriting the Window class, while my .cs partial class implements my WindowBase custom class. I can manually change the .g.cs file, but that is kind of a pain for every window I create.

Anyone else experience this?

Jonathan

# re: WPF: Inheriting from custom class instead of Window

left by Jonathan at 10/3/2007 5:52 AM Gravatar
Nevermind. I missed part of the xaml syntax. Nice article!

# re: WPF: Inheriting from custom class instead of Window

left by Laurent at 10/3/2007 5:54 AM Gravatar
Hi,

This is a symptom that you changed the base class in the XAML and forgot to change it in the code-behind, or the contrary (changed in the code behind and forgot to change it in the XAML). The class specified in the XAML and in the code behind must match.

You must NOT modify the .g.cs file, because it is generated (that's what ""g" stands for). Your changes will be overwritten every time you build your project.

HTH,
Laurent

# re: WPF: Inheriting from custom class instead of Window

left by Dmitriy at 10/9/2007 6:18 PM Gravatar
Hi Laurent!

This is great, that I have found your article! Wery good starting point for my testing so called "XAML + C#". :-)

I have also found a wounder, that Blend cannot handle abstract class. And one more point.

Why can I not do something like this:

<src:Display x:Class="Application1.Window1"
...
MouseLeftButtonDown="DragAttempt">

By running InitializeComponent(), I become an exception, that 'DragAttempt' value cannot be assigned to property 'MouseLeftButtonDown' of object 'Application1.Window1'. Error binding to target method.

If i do this in code like
this.MouseLeftButtonDown += new MouseButtonEventHandler(DragAttempt);
all works properly. Wery interesting. All works also by deriving from Window.

I have much more problems with events in WPF. I have seen it many times and it has happened to me where events just dont get raise. For examlpe this "MouseLeftButtonDown" never fires, in my application, when "linked" to button event button1.MouseLeftButtonDown, but fires, when "linked" to window, for example (see above). Have you ever seen such problems? I do something wrong, or this events is really can be lost? :-)

Have a nice day and good luck in Your work!

Dmitriy.

# re: WPF: Inheriting from custom class instead of Window

left by Bob Binette at 11/12/2007 5:52 AM Gravatar
The example work find with Visual Studio 2005 SP 1 + WPF extensions but it doesn't work with Visual Studio 2008 beta 2. For more details :

WPF (XAML) Visual Inheritance
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=289715

Bob

# re: WPF: Inheriting from custom class instead of Window

left by Laurent at 11/12/2007 7:09 AM Gravatar
Hi Bob,

No, you misunderstood my example. I am not doing XAML inheritance. The class WindowBase is a pure C# class.

What the "bug" in Connect describes is known as "Markup subclassing" and is explicitly warned against by Microsoft.
http://work.j832.com/2007/06/don-subclass-panel-unless-you-making.html

Greetings,
Laurent
Comments have been closed on this topic.