Наследование от UserControl в WPF - PullRequest
30 голосов
/ 06 ноября 2008

Я довольно новичок в WPF и у меня возникла проблема с наследованием от пользовательского элемента управления.

Я создал пользовательский элемент управления, и теперь мне нужно наследовать от этого элемента управления и добавить некоторые дополнительные функции.

Кто-нибудь делал подобные вещи раньше? Любая помощь будет принята с благодарностью.

Спасибо

Ответы [ 6 ]

27 голосов
/ 06 ноября 2008

Хорошо .. вы создаете свой базовый элемент управления

public abstract class BaseUserControl : UserControl{...}

затем в файле XAML:

<Controls:BaseUserControl x:Class="Termo.Win.Controls.ChildControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:Namespace.Of.Your.BaseControl">

И это должно сработать.

РЕДАКТИРОВАТЬ: Хмм .. этот пример полезен, когда у вас есть базовый элемент управления без XAML, а затем наследовать от него. И наоборот (из базового элемента управления с Xaml) - я не уверен, как вы можете это сделать.

РЕДАКТИРОВАТЬ 2: Как видно из этот пост + комментарии Я понимаю, что то, что вы хотите, может быть невозможным.

15 голосов
/ 07 ноября 2008

AFAIK, вы не можете наследовать xaml, вы можете только наследовать код позади.

Недавно мы столкнулись с той же проблемой в нашем проекте. В итоге мы решили нашу проблему, создав пользовательский контроль и добавив его в «дочерний» пользовательский контроль.

Если это не сработает / поможет взглянуть на это: http://geekswithblogs.net/lbugnion/archive/2007/03/02/107747.aspx 1

4 голосов
/ 23 июня 2009

У меня может быть немного решения: Композиция вместо наследования - я придумал элемент управления, который имеет «слоты контента», назначаемые извне через привязку данных, посмотрите на мой поток SO .

Пример использования:

<UserControl ... >

    <!-- My wrapping XAML -->
        <Common:DialogControl>
                <Common:DialogControl.Heading>
                        <!-- Slot for a string -->
                </Common:DialogControl.Heading>
                <Common:DialogControl.Control>
                        <!-- Concrete dialog's content goes here -->
                </Common:DialogControl.Control>
                <Common:DialogControl.Buttons>
                        <!-- Concrete dialog's buttons go here -->
                </Common:DialogControl.Buttons>
        </Common:DialogControl>
    <!-- /My wrapping XAML -->

</UserControl>

Вместе с некоторым кодом обработки в codebehind это будет хороший базовый компонент для диалоговых окон.

2 голосов
/ 20 октября 2011

Вы не можете наследовать код XAML сам. Однако создание абстрактного класса codebehind позволит вам редактировать его внутри кода из объекта производного класса.

Код Xaml: {Window1.xaml}

<Window 
x:Class="WPFSamples.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="auto" Width="256" Title="WPF Sameples">
  <Grid>
    <Button x:Name="Button1" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Click Me"/>
  </Grid>
</Window>

CodeBehind: {Window1.xaml.cs}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPFSamples
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public abstract partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
    }
}

Производный класс: {DisabledButtonWindow.cs}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WPFSamples
{
    public sealed class DisabledButtonWindow : Window1
    {
        public DisabledButtonWindow()
        {
            Button1.IsEnabled = false;
        }
    }
}

, хотя вы не можете наследовать от самого источника wpf, вы можете использовать этот элемент управления «Window1» в качестве шаблона для всех других производных элементов управления.

2 голосов
/ 30 января 2011

Вы можете сделать это, используя delegate.

По сути, вам необходимо создать интерфейс (YourInterface), который обернет нужные вам функции, а затем заставить пользовательский элемент управления и ваш класс реализовать этот интерфейс.

Затем убедитесь, что пользовательский элемент управления имеет ссылку на объект типа IYourInterface, поэтому, когда ваш пользовательский элемент управления пытается вызвать метод Interface, он вызывает метод вашего класса.

Поскольку и пользовательский элемент управления, и класс реализуют один и тот же интерфейс, они могут рассматриваться как объекты одного и того же типа - то есть вы можете поместить их обоих в коллекцию объектов типа IYourInterface. Это должно дать вам поведение, которое вы хотите.

В ASP.NET я часто использую эту технику, поскольку мои классы наследуются от abstract class предков. Я не понимаю, почему WPF не поддерживает это. (

1 голос
/ 25 апреля 2013

Я думаю, что вы можете сделать это, но вам придется переопределить любые функции и, возможно, некоторые другие вещи, на которые вы ссылаетесь в xaml в дочернем классе.

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

Не уверен на сто процентов в деталях, так как это код моего коллеги, из которого я рисую, но думал, что это даст старт любому, кто хочет реализовать это в будущем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...