【问题标题】:How can a WPF UserControl inherit a WPF UserControl?WPF UserControl 如何继承 WPF UserControl?
【发布时间】:2010-10-27 14:45:55
【问题描述】:

以下名为 DataTypeWholeNumber 的 WPF UserControl 有效。

现在我想制作一个名为 DataTypeDateTimeDataTypeEmail 等的 UserControl。

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

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

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



    }
}

【问题讨论】:

标签: c# wpf xaml user-controls


【解决方案1】:

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

所以

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

变成

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

所以,总结一下完整的答案,包括来自以下 cmets 的额外细节:

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

【讨论】:

  • 当我进行更改时,我收到错误消息:“...DataTypes.BaseDataType 不能是 XAML 文件的根,因为它是使用 XAML 定义的”,你如何摆脱这个循环引用?
  • 如果您可以使基类成​​为从 UserControl 继承的普通类型而不定义任何 xmal(因此不是将部分类拆分为两个文件)。问题是您不能继承 xmal,因此基类或子类都不需要有 xmal 文件。要么让你的类自定义控件而不是用户控件。这样,外观是在部分类之外定义的,但您将失去用户控件的易用性。
  • 就是这样:如果您将 BaseDataType 设为继承 UserControl 的普通类,那么它可以工作。太好了,谢谢。
  • @Martin 您可能想更新您的答案以反映您的评论,这是真正的答案。
  • 有没有办法让“控制基础”中的元素在继承类的元素之上?
【解决方案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>    

【讨论】:

    【解决方案3】:

    我在这篇文章中找到了答案:http://www.paulstovell.com/xmlnsdefinition

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

    【讨论】:

      【解决方案4】:

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

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

      因此,您可以将 CustomControl 设置为基类而不是 UserControl,以避免在基类中进行部分定义(如评论中所述)。

      【讨论】:

      • 无法从 Controls.Login 转换为 Controls.BaseControl。
      • 在我的情况下(Visual Studio 2019),这会在构建解决方案后恢复为 UserControl
      【解决方案5】:

      我遇到了同样的问题,但需要从抽象类继承控件,而设计器不支持。解决我的问题是让用户控件继承自标准类(继承用户控件)和接口。设计师就是这样工作的。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多