Як WPF UserControl може успадкувати WPF UserControl?


92

Наступний WPF UserControl називається DataTypeWholeNumber, який працює.

Тепер я хочу зробити UserControl з назвою DataTypeDateTime і DataTypeEmail тощо.

Багато Властивостей залежності будуть спільними для всіх цих елементів керування, і тому я хочу застосувати їх загальні методи до 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());



    }
}

про обхід WPF з візуальним успадкуванням див .: svetoslavsavov.blogspot.gr/2009/09/… або про явне визначення графічного інтерфейсу в предку див. support.microsoft.com/kb/957231
Джордж Бірбіліс

Відповіді:


130

Переконайтеся, що ви змінили перший тег у 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-коду, так і в першому тезі xaml (як показано вище).

4
коли я вношу цю зміну, я отримую помилку: "... DataTypes.BaseDataType не може бути коренем файлу XAML, оскільки він був визначений за допомогою XAML", як ви виходите з цього кругового посилання?
Едвард Тангвай

9
Якщо ви можете просто зробити базовий клас звичайним типом, який успадковується від UserControl, не визначаючи жодного xmal (тому не частковий клас, розділений на два файли). Проблема в тому, що ви не можете успадкувати xmal, тому або базовий, або дочірній клас не повинні мати файлу xmal. Або це, або зробіть свої класи нестандартними елементами керування, а не елементами керування користувача. Таким чином зовнішній вигляд визначається поза частковим класом, але ви втратите простоту користувацького контролю.
Мартін Гарріс,

1
Ось і все: якщо ви зробите 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>    

1

Відповідь я знайшов у цій статті: http://www.paulstovell.com/xmlnsdefinition

В основному сказано те, що ви повинні визначити простір імен XML у файлі AssemlyInfo.cs, який можна використовувати в XAML. Це спрацювало для мене, однак я помістив базовий клас управління користувачем в окрему DLL ...


0

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

0

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

Після цього ви отримаєте попередження про те, що метод InitializeComponent () прихований у дочірньому класі.

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


Неможливо перетворити з Controls.Login на Controls.BaseControl.
Хімілу
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.