WPF’s Use of Partial Classes’ Access Modifiers

While writing a reusable component for a client, I placed it in a different assembly and began to change all of the non-public classes’ access modifiers to internal. Building the project, I received the following error:

error CS0262: Partial declarations of ‘ClassName’ have conflicting accessibility modifiers.

The two conflicting source files were my original ClassName.xaml.cs file and the automatically generated ClassName.g.cs file. It appeared that the ClassName.g.cs stated that my class was still public. Here are my types:

MyWindow.cs:

internal partial class MyWindow : Window

MyWindow.g.cs:

public partial class MyWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector

After a bit of digging, I found the culprit. Apparently, when you have a non-public modifier, you have to qualify your element with the x:ClassModifier attribute. In my case, the code looked like this:

<Window x:Class="MyNamepsace.MyWindow" x:ClassModifier="internal"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

All works and all is well in the world… Well, not everything. You see, this is both ugly and easily avoidable.

Why is this ugly? The x:ClassModifier attribute clearly states that the string passed to it:

[…] varies, depending on the code-behind programming language being used.

This makes your XAML file’s correctness bound to the language the code-behind is written in, rather than be language-neutral and CLR-centric.

Another assumption made by WPF’s design team was that the default value is public, which means every type is added to the list of publicly visible types in your assembly by default. If you write a client application, this may not be of any concern to you, but if you write reusable components, this is a highly important design decision. On the other hand, this might just be me nitpicking.

How could this be avoided? As you may well know, when defining a partial class, the definition is collected from every part, glued together, and only then are default behaviors appended and the code is compiled. This means that if you fail to write an access modifier in one file and only write it in another, there will be an access modifier, but on the other hand, writing two conflicting modifiers will cause a compiler error.

This means that the only thing needed to be done to avoid the entire need for the x:ClassModifier attribute was to emit generated code with no access modifier and have the code-behind implicitly take control of it.

Final words: This can also be found in base class references, where all partial classes are marked as deriving from the same base type, as you can see in the examples above. Then again, this may just be a safeguard against people messing with their base classes… who knows.
I hope this would go away in the next version of the designer. Is anyone listening?

Advertisements

7 thoughts on “WPF’s Use of Partial Classes’ Access Modifiers

  1. This is actually strange because if I add a button to a WPF form in the designed in vc# 2008 express and look at the generated code, it defines it as internal, not public as you say.
    Actually I searched a way to change that to some other value as well so I started searching – and found your post. I still don’t know how to specify the access modifier of a control I add to an WPF form.

  2. Marc,
    This post actually refers to the access modifier of the main class in the file.
    If you want to do what you’re looking for, use x:FieldModifier instead.
    And yes, I can’t understand why they’d use ‘internal’ as the default for that either…

  3. Something I’ve been wondering myself… WPF is chock full of idiocies like this. My personal guess is that the person behind the C# codegen was not intimately familiar with the workings of C#’s partial classes, which were specifically designed for this scenario by people far smarter than the creators of WPF. But WPF found a way to mess it up.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s