C# WPF UserControl 如何继承 WPF UserControl?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/887519/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 08:29:10  来源:igfitidea点击:

How can a WPF UserControl inherit a WPF UserControl?

c#wpfxamluser-controls

提问by Edward Tanguay

The following WPF UserControl called DataTypeWholeNumberwhich works.

以下 WPF UserControl 称为DataTypeWholeNumber,它可以工作。

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

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

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

许多依赖属性将由所有这些控件共享,因此我想将它们的通用方法放入 BaseDataType并让这些 UserControl 中的每一个都从该基类型继承。

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

但是,当我这样做时,出现错误: 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?

那么如何使用 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());



    }
}

采纳答案by Martin Harris

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

确保您已将 xaml 中的第一个标记更改为也继承自新的基本类型

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).
  • 基类不应包含 xaml 文件。在单个(非部分)cs 文件中定义它,并将其定义为直接从 Usercontrol 继承。
  • 确保子类在 cs 代码隐藏文件和 xaml 的第一个标记中都继承自基类(如上所示)。

回答by knee-cola

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

我在这篇文章中找到了答案: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...

基本上是说你应该在 AssemlyInfo.cs 文件中定义一个 XML 命名空间,它可以在 XAML 中使用。它对我有用,但是我将基本用户控件类放在单独的 DLL 中...

回答by Sam L.

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

回答by Petar

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>    

回答by Kakha Middle Or

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

设计器创建了部分类定义,您可以通过 InitializeComponent() 方法定义轻松打开它。然后只需将部分类继承从 UserControl 更改为 BaseDataType (或您在类定义中指定的任何内容)。

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

之后,您将收到 InitializeComponent() 方法隐藏在子类中的警告。

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

因此,您可以将 CustomControl 作为基类而不是 UserControl 以避免基类中的部分定义(如一条评论中所述)。