The WPF UserControl experiment 1

Goal: 
To create a WPF user control that implements basic functionality from a  non-GUI interface, and delegating the rest through abstract methods.

Attempt 1:

  1. Defined a base WPF user control BaseWpfControl using XAML.
    public abstract partial class BaseWpfCustomPropertyEditor : UserControl, Interface1 { …}
  2. Then, extend BaseWpfControl, like so:
    <local:BaseWpfControl x:Class="MyNameSpace.LoginEditorControl"
       xmlns="
    http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="
    http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MyNameSpace"
        Height="206" Width="595">
        <Grid Height="300" Width="418">
            <Grid Margin="10,10,-75,120">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="210*" />
                    <ColumnDefinition Width="118*" />
                    <ColumnDefinition Width="155*" />
                </Grid.ColumnDefinitions>
                <Label Height="33" Margin="6,-1,67,0" Name="label1" VerticalAlignment="Top">Host Name:</Label>
                <TextBox Height="23" Margin="12,25,23,0" Name="txtHostName" TextChanged="txtHostName_TextChanged" VerticalAlignment="Top" Grid.ColumnSpan="3" />
                <Label Height="29" Margin="6,47,88,0" Name="label2" VerticalAlignment="Top">User Name:</Label>
                <TextBox Height="23" Margin="12,71,23,0" Name="textBox1" VerticalAlignment="Top" Grid.ColumnSpan="3" TextChanged="textBox1_TextChanged" />
                <Label Height="25" Margin="6,102,94,0" Name="label3" VerticalAlignment="Top">Password:</Label>
                <PasswordBox Height="23" Margin="12,133,23,0" Name="passwordBox1" VerticalAlignment="Top" Grid.ColumnSpan="3" PasswordChanged="passwordBox1_PasswordChanged" />
            </Grid>
        </Grid>
    </local:BaseWpfCustomPropertyEditor>
  3. Got compile-time error: "cannot be the root of a XAML file because it was defined using XAML""

Conclusion: WPF user controls were designed for composition, not inheritance.

Attempt 2:

  1. Instead of using XAML, simply defined  BaseWpfControl as a class that extends System.Windows.Controls.UserControl
  2. Repeat Attempt 1.2
  3. Now compiles fine. But when trying to bring up LoginEditorControl, got error:
    Problem Loading … Could not create an instance of  type “BaseWpfControl…”
  4. Double-checked, BaseWpfControl did have a default constructor
  5. Removed abstract partial keyword in base class  Same problem
  6. Searched the web; found this https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=292693:
    ”Hello, if you mark your base generic class as abstract, the designer does not work. I understand this might not be a supported scenario and I'd live with this, if:
    1) it would not work with non-abstract classes as well,
    2) all the XAML code would not get underlined, that is really crazy.”

Sub-Goal 1.1:

  • how to make an abstract WPF base control editable in the UI designer?

Attempt 1.1.1:

  1. Per http://www.urbanpotato.net/default.aspx/document/2001, annotated BaseWpfControl with
    [TypeDescriptionProvider(typeof(GeneralConcreteClassProvider))]
    [ConcreteClass(typeof(UserControl))]
  2. didn’t help … same error “Could not create an instance of …”

Attempt 1.1.2:

  1. Removed abstract keyword from BaseWpfControl .
  2. Bring LoginEditorControl control back in the VS2008 Visual Designer. Got message:
    The document root element is not supported by the visual designer
  3. Changing base class for BaseWpfControl to ContentControl didn’t help.
  4. If we changed to using XAML for BaseWpfControl, then we’d be back to problem 1.3

Attempt 1.1.3: immediate work-around

  1. Remove abstract keyword from BaseWpfControl
  2. commented out the line:
    public partial class LoginEditorControl : UserControl, BaseWpfControl { 
  3. Replaced with:
    public partial class LoginEditorControl : UserControl {
  4. Replaced XAML declaration
    <local:BaseWpfControl  x:Class="MyLib1.LoginEditorControl " xmlns:local="clr-namespace:MyLib1"
    with
    <UserControl
  5. Edit the control in VS Visual Designer, then undo steps 1-4 prior to running.

Stopped experimenting here. If I had had more time, I would have liked to try these:

Attempt 1.1.4: better workaround – use XamlPad
Previous process was too cumbersome to undo. Use XamlPad to edit the control GUI, and then paste he result back to the VS project.

Attempt 1.1.5: How to overcome restriction of “multiple class inheritance”?
Use Events instead.

5 comments:

kulvir.com said...
This comment has been removed by the author.
kulvir.com said...

Did you try using the property:
DesignerProperties.GetIsInDesignMode

th2tran said...

No, I haven't, but will try on the next opportunity. Thanks for the tip.

Shimmy said...

They suck
Microsoft's employees are so ignorant

Anonymous said...

what if DesignerProperties.GetIsInDesignMode also doesnt work?