web-dev-qa-db-fra.com

Héritage d'un UserControl dans WPF

Je suis assez nouveau sur WPF et j'ai un problème avec l'héritage d'un contrôle utilisateur.

J'ai créé un contrôle utilisateur et maintenant je dois hériter de ce contrôle et ajouter des fonctionnalités supplémentaires.

Quelqu'un a-t-il déjà fait ce genre de choses? Toute aide serait grandement appréciée.

Je vous remercie

30
user35129

AFAIK vous ne pouvez pas hériter du xaml, vous ne pouvez hériter que du code derrière.

Nous avons récemment rencontré le même problème sur notre projet. La façon dont nous avons fini par résoudre notre problème était de créer un contrôle utilisateur et de l'ajouter au contrôle utilisateur "enfant".

Si cela ne fonctionne pas/aide, jetez un œil à ceci: http://geekswithblogs.net/lbugnion/archive/2007/03/02/107747.aspx1

15
BFreeman

Eh bien .. vous créez votre contrôle de base

public abstract class BaseUserControl : UserControl{...}

puis dans le fichier 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">

Et ça devrait marcher.

EDIT: Hmm .. cet exemple est utile lorsque vous avez un contrôle de base sans XAML et que vous en héritez ensuite. L'inverse (à partir d'un contrôle de base avec Xaml) - je ne sais pas comment vous pouvez vous y prendre.

EDIT2: Apparemment de cet article + commentaires je suppose que ce que vous voulez pourrait ne pas être possible.

27
sirrocco

J'ai peut-être une petite solution: la composition au lieu de l'héritage - j'ai trouvé le contrôle, qui a des 'slots de contenu' assignables de l'extérieur via la liaison de données, regardez mon SO thread .

Exemple d'utilisation:

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

Avec un peu de code de gestion dans codebehind, ce serait un composant de base agréable pour les fenêtres de dialogue.

4
Tomáš Kafka

Vous ne pouvez pas hériter du code xaml lui-même. Cependant, la création d'une classe abstraite du codebehind, vous permettra de modifier le code derrière, à partir d'un objet de classe dérivé.

Code 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();
        }
    }
}

Classe dérivée: {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;
        }
    }
}

bien que vous ne puissiez pas hériter de la source wpf elle-même, vous pouvez utiliser ce contrôle "Window1" comme modèle pour tous les autres contrôles dérivés.

3
user1005465

Vous pouvez accomplir cela en utilisant un delegate.

Essentiellement, vous devez créer une interface (YourInterface) qui englobe les fonctionnalités souhaitées, puis faire en sorte que le contrôle utilisateur et votre classe implémentent cette interface.

Ensuite, assurez-vous que le contrôle utilisateur a une référence à un objet de type IYourInterface, de sorte que lorsque votre contrôle utilisateur tente d'appeler une méthode du Interface, il appelle la méthode de votre classe.

Étant donné que le contrôle utilisateur et la classe implémentent la même interface, ils peuvent être vus comme le même type d'objet, ce qui signifie que vous pouvez les placer tous les deux dans une collection d'objets de type IYourInterface. Cela devrait vous donner le comportement que vous souhaitez.

Dans ASP.NET, j'utilise souvent cette technique, en faisant hériter mes classes de abstract class les ancêtres. Je ne comprends pas pourquoi WPF ne prend pas en charge cela. :(

1
Maximiliano

Je pense que vous pouvez le faire mais que vous devrez redéfinir toutes les fonctions et éventuellement d'autres éléments que vous référencez dans le xaml dans la classe enfant.

IE si vous avez un événement de clic de bouton auquel vous êtes abonné dans la classe de base xaml, vous devrez remplacer le clic de bouton dans la classe enfant et appeler l'événement de clic de bouton de la classe de base.

Je ne suis pas sûr à 100% des détails, car c'est mon code de collègues que je tire, mais je pensais que cela donnerait un début à quiconque cherchait à l'implémenter à l'avenir.

1
Matthew Beatty