104

The following WPF UserControl called DataTypeWholeNumber which works.

Now I want to make a UserControl called DataTypeDateTime and DataTypeEmail, etc.

Many of the Dependency Properties will be shared by all these controls and therefore I want to put their common methods into a BaseDataType and have each of these UserControls inherit from this base type.

However, when I do that, I get the error: Partial Declaration may not have different base classes.

So how can I implement inheritance with UserControls so shared functionality is all in the base class?

using System.Windows;
using System.Windows.Controls;

namespace TestDependencyProperty827.DataTypes
{
    public partial class DataTypeWholeNumber : BaseDataType
    {
        public DataTypeWholeNumber()
        {
            InitializeComponent();
            DataContext = this;

            //defaults
            TheWidth = 200;
        }

        public string TheLabel
        {
            get
            {
                return (string)GetValue(TheLabelProperty);
            }
            set
            {
                SetValue(TheLabelProperty, value);
            }
        }

        public static readonly DependencyProperty TheLabelProperty =
            DependencyProperty.Register("TheLabel", typeof(string), typeof(BaseDataType),
            new FrameworkPropertyMetadata());


        public string TheContent
        {
            get
            {
                return (string)GetValue(TheContentProperty);
            }
            set
            {
                SetValue(TheContentProperty, value);
            }
        }

        public static readonly DependencyProperty TheContentProperty =
            DependencyProperty.Register("TheContent", typeof(string), typeof(BaseDataType),
            new FrameworkPropertyMetadata());


        public int TheWidth
        {
            get
            {
                return (int)GetValue(TheWidthProperty);
            }
            set
            {
                SetValue(TheWidthProperty, value);
            }
        }

        public static readonly DependencyProperty TheWidthProperty =
            DependencyProperty.Register("TheWidth", typeof(int), typeof(DataTypeWholeNumber),
            new FrameworkPropertyMetadata());



    }
}
Askolein
  • 3,250
  • 3
  • 28
  • 40
Edward Tanguay
  • 189,012
  • 314
  • 712
  • 1,047
  • for WPF workaround with Visual inheritance see: http://svetoslavsavov.blogspot.gr/2009/09/user-control-inheritance-in-wpf.html or for explicitly defining the GUI in the ancestor see http://support.microsoft.com/kb/957231 – George Birbilis Jan 10 '15 at 01:44

5 Answers5

146

Ensure that you have changed the first tag in the xaml to also inherit from your new basetype

So

<UserControl x:Class="TestDependencyProperty827.DataTypes.DataTypeWholeNumber"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
    xmlns:s="clr-namespace:System;assembly=mscorlib"
    >

becomes

<myTypes:BaseDataType x:Class="TestDependencyProperty827.DataTypes.DataTypeWholeNumber"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
    xmlns:s="clr-namespace:System;assembly=mscorlib"
    xmlns:myTypes="clr-namespace:TestDependencyProperty827.DataTypes"
    >

So, to summarise the complete answer including the extra details from the comments below:

  • The base class should not include a xaml file. Define it in a single (non-partial) cs file and define it to inherit directly from Usercontrol.
  • Ensure that the subclass inherits from the base class both in the cs code-behind file and in the first tag of the xaml (as shown above).
Mizipzor
  • 51,151
  • 22
  • 97
  • 138
Martin Harris
  • 28,277
  • 7
  • 90
  • 101
  • 4
    when I make that change I get the error: "...DataTypes.BaseDataType cannot be the root of a XAML file because it was defined using XAML", how do you get out of this circular reference? – Edward Tanguay May 20 '09 at 12:16
  • 10
    If you can just make the base class a normal type that inherits from UserControl without defining any xmal (so not a partial class split over two files). The problem is that you can't inherit xmal, so either the base or child class need to not have a xmal file. Either that or make your classes custom controls instead of a user controls. That way the appearance is defined outside of the partial class but you'll lose the ease of use of a User Control. – Martin Harris May 20 '09 at 12:24
  • 1
    That's it: if you make BaseDataType a normal class that inherits UserControl, then it works. Excellent, thanks. – Edward Tanguay May 20 '09 at 12:32
  • @Martin you might want to update your answer to reflect your comment and it's the real answer. – Bryan Anderson May 20 '09 at 14:28
  • Is there a way to make the elements from "control base" are on top of the ones on class that inherits? – Juan M. Elosegui Dec 01 '12 at 14:40
  • Thanks ! Actually, perhaps back then in 2010, partial **cs** (code behind only) files weren't allowed, but you ***can*** make partial cs (no xaml) files for the base class (at least now, don't know back then) Just pointing that out since the phrasing _"Define it in a **single** (non-partial) cs file..."_ looks somewhat inaccurate (the more since _"no xaml"_ was explicitely stated right before) – Karl Stephen Jan 17 '15 at 03:23
  • 1
    Also take care that your base class must have parameterless constructor and that some properties in derived class xaml should have namespace qualifier like x:Name instead just Name. – watbywbarif Mar 31 '15 at 13:00
2
public partial class MooringConfigurator : MooringLineConfigurator
    {
        public MooringConfigurator()
        {
            InitializeComponent();
        }
    }



<dst:MooringLineConfigurator x:Class="Wave.Dashboards.Instruments.ConfiguratorViews.DST.MooringConfigurator"
    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"
    xmlns:dst="clr-namespace:Wave.Dashboards.Instruments.ConfiguratorViews.DST"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">

    </Grid>
</dst:MooringLineConfigurator>    
Pitka
  • 525
  • 5
  • 12
1

There is partial class definition created by designer, you can open it easy way via InitializeComponent() method definition. Then just change partial class iheritence from UserControl to BaseDataType (or any you specified in class definition).

After that you will have warning that InitializeComponent() method is hidden in child class.

Therefore you can make a CustomControl as base clas instead of UserControl to avoid partial definition in base class (as described in one comment).

Bartłomiej Semańczyk
  • 59,234
  • 49
  • 233
  • 358
Kakha Middle Or
  • 166
  • 1
  • 6
1

I found the answer in this article: http://www.paulstovell.com/xmlnsdefinition

Basically what is says is that you should define an XML namespace in the AssemlyInfo.cs file, which can the be used in the XAML. It worked for me, however I placed the base user control class in a separate DLL...

knee-cola
  • 736
  • 8
  • 17
0

I ran into the same issue but needed to have the control inherit from an abstract class, which is not supported by the designer. What solved my problem is making the usercontrol inherit from both a standard class (that inherits UserControl) and an interface. This way the designer is working.

//the xaml
<local:EcranFiche x:Class="VLEva.SIFEval.Ecrans.UC_BatimentAgricole" 
                  xmlns:local="clr-namespace:VLEva.SIFEval.Ecrans"
                  ...>
    ...
</local:EcranFiche>

// the usercontrol code behind
public partial class UC_BatimentAgricole : EcranFiche, IEcranFiche
{
    ...
}

// the interface
public interface IEcranFiche
{
   ...
}

// base class containing common implemented methods
public class EcranFiche : UserControl
{
    ... (ex: common interface implementation)
}
Sam L.
  • 207
  • 2
  • 3