WPF UserControl สามารถสืบทอด WPF UserControl ได้อย่างไร


95

WPF UserControl ต่อไปนี้เรียกว่าDataTypeWholeNumberซึ่งใช้งานได้

ตอนนี้ฉันต้องการสร้าง UserControl ชื่อDataTypeDateTimeและDataTypeEmailเป็นต้น

คุณสมบัติการพึ่งพาจำนวนมากจะถูกใช้ร่วมกันโดยการควบคุมเหล่านี้ทั้งหมดดังนั้นฉันจึงต้องการใส่วิธีการทั่วไปลงใน BaseDataTypeและให้ UserControl แต่ละตัวสืบทอดมาจากประเภทพื้นฐานนี้

แต่เมื่อฉันทำอย่างนั้นฉันจะได้รับข้อผิดพลาดชี้แจงบางส่วนอาจไม่ได้มีฐานเรียนที่แตกต่างกัน

ดังนั้นฉันจะใช้การสืบทอดกับ UserControl ได้อย่างไรเพื่อให้ฟังก์ชันการทำงานที่แชร์ทั้งหมดอยู่ในคลาสพื้นฐาน

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 ด้วย Visual inheritance โปรดดู: svetoslavsavov.blogspot.gr/2009/09/…หรือสำหรับการกำหนด GUI ในบรรพบุรุษอย่างชัดเจนโปรดดูsupport.microsoft.com/kb/957231
George Birbilis

คำตอบ:


132

ตรวจสอบให้แน่ใจว่าคุณได้เปลี่ยนแท็กแรกใน 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 (ดังที่แสดงด้านบน)

4
เมื่อฉันทำการเปลี่ยนแปลงฉันได้รับข้อผิดพลาด: "... DataTypes.BaseDataType ไม่สามารถเป็นรูทของไฟล์ XAML ได้เพราะถูกกำหนดโดยใช้ XAML" คุณจะออกจากการอ้างอิงแบบวงกลมนี้ได้อย่างไร?
Edward Tanguay

9
หากคุณสามารถทำให้คลาสพื้นฐานเป็นประเภทปกติที่สืบทอดมาจาก UserControl โดยไม่ต้องกำหนด xmal ใด ๆ (ดังนั้นไม่ใช่การแบ่งคลาสบางส่วนในสองไฟล์) ปัญหาคือคุณไม่สามารถสืบทอด xmal ได้ดังนั้นทั้งฐานหรือคลาสลูกไม่จำเป็นต้องมีไฟล์ xmal อย่างใดอย่างหนึ่งหรือทำให้คลาสของคุณควบคุมแบบกำหนดเองแทนการควบคุมของผู้ใช้ ด้วยวิธีนี้ลักษณะที่ปรากฏจะถูกกำหนดไว้ภายนอกคลาสบางส่วน แต่คุณจะสูญเสียความสะดวกในการใช้งาน User Control
Martin Harris

1
นั่นแหล่ะ: ถ้าคุณสร้าง BaseDataType เป็นคลาสปกติที่สืบทอด UserControl มันก็จะใช้งานได้ ยอดเยี่ยมขอบคุณ
Edward Tanguay

@Martin คุณอาจต้องการอัปเดตคำตอบเพื่อแสดงความคิดเห็นของคุณและเป็นคำตอบที่แท้จริง
Bryan Anderson

มีวิธีทำให้องค์ประกอบจาก "ฐานควบคุม" อยู่ด้านบนของชั้นเรียนที่สืบทอดมาหรือไม่?
Juan M. Elosegui

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 สืบทอดจากคลาสมาตรฐาน (ที่สืบทอด 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 ล็อกอินเป็น Controls.BaseControl
Himilou
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.