Как WPF UserControl наследует WPC UserControl?

Следующий пользовательский элемент управления WPF называется DataTypeWholeNumber, который работает.

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

Многие из свойств зависимостей будут совместно использоваться всеми этими элементами управления, и поэтому я хочу поместить их общие методы в BaseDataType, и каждый из этих UserControls наследует от этого базового типа.

Однако, когда я это делаю, я получаю ошибку: Partial Declaration может не иметь разных базовых классов.

Итак, как я могу реализовать наследование с помощью 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());



    }
}

Ответ 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"
    >

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

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

Ответ 2

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

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

Ответ 3

Я столкнулся с той же проблемой, но мне нужно было наследовать элемент управления от абстрактного класса, который не поддерживается дизайнером. То, что решило мою проблему, - это наследование 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)
}

Ответ 4

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>    

Ответ 5

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

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

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