XAML without the .xaml.cs code behind files
Asked Answered
S

5

30

I'm using WPF with the Model-View-ViewModel pattern. Thus, my code behind files (.xaml.cs) are all empty, except for the constructor with a call to InitializeComponent. Thus, for every .xaml file I have a matching, useless, .xaml.cs file.

I swear I read somewhere that if the code behind file is empty except for the constructor, there is a way to delete the file from the project altogether. After searching the net, it seems that the appropriate way to do this is to use the 'x:Subclass' attribute:

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    xmlns:toolkit="http://schemas.microsoft.com/wpf/2008/toolkit"
    x:Class="MyNamespace.MyClass"
    x:Subclass="UserControl"
    d:DesignWidth="700" d:DesignHeight="500">

This does the following in the generated .g.cs file:

  1. Removes the 'partial' class modifier on MyClass.
  2. Adds the class 'UserControl' in to its subclass list.

Seems perfect. Indeed, if you still have the .xaml.cs file in the build, it no longer compiles because of the missing partial--so I'm thinking this must be correct. However, if I remove the superfluous file from the build and run, the control does not get initialized correctly (it is blank). This is, I presume, because InitializeComponent() is not getting called. I see InitializeComponent is not virtual, so it seems there would be no way for the base class to call it (short of using reflection).

Am I missing something?

Thanks!

Eric

Samples answered 3/12, 2009 at 17:46 Comment(0)
N
16

If you follow Josh Smith's MVVM article, he uses DataTemplates for Views rather than user controls. If you put your DataTemplates into ResourceDictionaries, they don't have a code-behind at all. If you're not using the code-behind of your user control, doesn't that mean you could use a DataTemplate approach? If you do that, WPF will take care of binding your View to your ViewModel for you.

Norahnorbert answered 5/12, 2009 at 2:15 Comment(3)
Thanks Scott. This is a definitely a better approach.Samples
+1 I also use this way. It works so great it's almost like magic.Ossetia
Note: <x:Code> is available in WPF, but not Silverlight.Rummage
S
36

As another option, if you don't want to go all the way to using DataTemplates, here is an alternate approach for UserControls:

Use the x:Code attribute to embed the constructor call in the XAML:

<x:Code><![CDATA[ public MyClass() { InitializeComponent(); }]]></x:Code>

Eric

Samples answered 3/12, 2009 at 18:14 Comment(5)
That's a very slick solution.Bursitis
sweet. who'd have thought of that?Ossetia
well... I upvote this, as it's very clever, but there's something that just doesn't feel right about having this sort of CDATA code in your XAML files... Like someone else asked in a similar topic, why do we want to go through the trouble of removing the empty code-behind files at all? they're no bother, one can hardly see them sitting there. Still, I like your creativity :-)Wycliffite
We have a rule around here that the only thing that can go in the CDATA is the constructor with InitializeComponent(). Anything else, and it shall be in code behind.Samples
As far as why get rid of the code-behind--I guess it's because I am a purist. If I'm going to use Model-View-ViewModel, it urks me to have yet another file: Model-View-CodeBehind-ViewModel. I'm learning to like MVVM, but I try to avoid any code-behind magic between the V and the VM. Also, as a programmer I need to know if there is magic. If I don't see a code-behind file, I know there is none.Samples
N
16

If you follow Josh Smith's MVVM article, he uses DataTemplates for Views rather than user controls. If you put your DataTemplates into ResourceDictionaries, they don't have a code-behind at all. If you're not using the code-behind of your user control, doesn't that mean you could use a DataTemplate approach? If you do that, WPF will take care of binding your View to your ViewModel for you.

Norahnorbert answered 5/12, 2009 at 2:15 Comment(3)
Thanks Scott. This is a definitely a better approach.Samples
+1 I also use this way. It works so great it's almost like magic.Ossetia
Note: <x:Code> is available in WPF, but not Silverlight.Rummage
P
2

I had a discussion with a Windows Client team member at PDC about this, and right now, was told that there is no officially supported way to completely eliminate the code behind file. As you can see, you can get it to compile, but InitializeComponent() is never called, so the control doesn't get setup properly.

The x:Subclass attribute "usage is primarily intended for languages that do not support partial class declarations." It was not intended to allow this behavior (unfortunately).

Predigestion answered 3/12, 2009 at 18:9 Comment(0)
I
1

If you are using caliburn micro you can effectively remove .xaml.cs, the framework takes care of initialization (i.e. if you are going with the view-model approach).

This is discussed https://caliburnmicro.codeplex.com/discussions/444250

Indoors answered 25/5, 2013 at 1:48 Comment(0)
C
0

Out of sheer curiosity, have you tried using this:

x:Subclass="Control"

By default, UserControls require the InitializeComponent() call, but defacto-standard Controls do not. I'd be interested to see if this works.

-Doug

Cetacean answered 3/12, 2009 at 22:35 Comment(1)
Just tried this. It did not change the behavior. Without the call to InitializeComponent(), the control is blank.Samples

© 2022 - 2024 — McMap. All rights reserved.