Как WPF UserControl может наследовать WPF UserControl?

следующий WPF UserControl называется DataTypeWholeNumber который работает.

теперь я хочу сделать UserControl под названием DataTypeDateTime и DataTypeEmail, etc.

многие свойства зависимостей будут совместно использоваться всеми этими элементами управления, и поэтому я хочу поставить их общие методы в 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());



    }
}

5 ответов


убедитесь, что вы изменили первый тег в xaml, чтобы также наследовать от нового basetype

Так

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

Итак, подводя итог полный ответ, включая дополнительные детали из комментариев ниже:

  • базовый класс не должен включать файл xaml. Определите его в одном (неполном) cs-файле и определите его для наследования непосредственно от Usercontrol.
  • убедитесь, что подкласс наследует от базового класса как в файле кода cs, так и в первом теге xaml (как показано выше).

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>    

Я нашел ответ в этой статье: http://www.paulstovell.com/xmlnsdefinition

в основном говорится, что вы должны определить пространство имен XML в AssemlyInfo.cs-файл, который может использоваться в XAML. Это сработало для меня, однако я поместил базовый класс пользовательского управления в отдельную DLL...


я столкнулся с той же проблемой, но должен был наследовать элемент управления от абстрактного класса, который не поддерживается конструктором. То, что решило мою проблему, делает usercontrol наследуемым как от стандартного класса (который наследует UserControl), так и от интерфейса. Так работает дизайнер.

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

существует частичное определение класса, созданное дизайнером, вы можете легко открыть его с помощью определения метода InitializeComponent (). Затем просто измените частичный класс iheritence из UserControl на BaseDataType (или любой, указанный в определении класса).

после этого у вас будет предупреждение, что метод InitializeComponent() скрыт в дочернем классе.

поэтому вы можете сделать CustomControl как базовый класс вместо UserControl, чтобы избежать частичного определения в базовом классе (как описано в одном комментарии).