WPF 用户控件如何继承 WPF 用户控件?

以下名为 DataTypeWhole 数据类型的 WPF 用户控件可以工作。

现在我想创建一个名为 DataTypeDateTimeDataTypeEmail的 UserControl,等等。

许多依赖项属性将由所有这些控件共享,因此我希望放置 将它们的公共方法转换为 BaseDataType,并让这些 UserControls 中的每一个都从这个基类型继承。

然而,当我这样做的时候,我得到了 错误: 部分声明可能没有不同的基类

那么我如何用 UserControls 实现继承,以便共享功能都在基类中?

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());






}
}
66880 次浏览

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).

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...

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)
}
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>

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).