web-dev-qa-db-fra.com

Appel d'un constructeur paramétré à partir de XAML

Lors de l'utilisation de WPF, j'ai remarqué que lorsque j'ajoute un contrôle à un fichier XAML, le constructeur par défaut est appelé.

Existe-t-il un moyen d'appeler un constructeur paramétré?

57
Hani

.NET 4.0 apporte une nouvelle fonctionnalité qui remet en question la réponse.

x: Directive Arguments

<object ...>
    <x:Arguments>
        oneOrMoreObjectElements
    </x:Arguments>
</object>
72
Raskal

Je me rends compte que je suis en retard à la fête ici, mais comme personne n'a vraiment abordé les conventions WPF, je pensais que j'interviendrais.

L'un des principes directeurs des objets compatibles avec XAML est qu'ils doivent être complètement utilisables avec un constructeur par défaut, c'est-à-dire qu'aucun comportement n'est accessible uniquement lors de l'utilisation d'un constructeur non par défaut. Pour s'adapter à la nature déclarative de XAML, les paramètres d'objet sont spécifiés via des paramètres de propriété. Il existe également une convention qui dit que l'ordre dans lequel les propriétés sont définies dans XAML ne devrait pas être important.

Cependant, vous pouvez avoir des considérations spéciales qui sont importantes pour votre mise en œuvre mais en contradiction avec la convention:

  1. Vous pouvez avoir une ou plusieurs propriétés qui doit être définies avant que l'objet puisse être utilisé.
  2. Deux propriétés ou plus peuvent s'exclure mutuellement, par exemple, cela n'a aucun sens de définir à la fois StreamSource et UriSource d'une image.
  3. Vous pouvez vous assurer qu'une propriété est niquement définie lors de l'initialisation.
  4. Une propriété peut dépendre d'une autre, ce qui peut être délicat en raison de la convention susmentionnée d'indépendance de l'ordre lors de la définition des propriétés.

Pour faciliter la gestion de ces cas, l'interface ISupportInitialize est fournie. Lorsqu'un objet est lu et créé à partir de XAML (c'est-à-dire analysé), les objets implémentant ISupportInitialize seront traités spécialement:

  1. Le constructeur par défaut sera appelé.
  2. BeginInit() sera appelée.
  3. Les propriétés seront définies dans leur ordre d'apparition dans la déclaration XAML.
  4. EndInit() est appelée.

En suivant les appels à BeginInit() et EndInit(), vous pouvez gérer toutes les règles que vous devez imposer, y compris l'exigence que certaines propriétés soient définies. C'est ainsi que vous devez gérer les paramètres de création; pas en exigeant des arguments de constructeur.

Notez que ISupportInitializeNotification est également fourni, ce qui étend l'interface ci-dessus en ajoutant une propriété IsInitialized et un événement Initialized. Je recommande d'utiliser la version étendue.

27
Mike Strobel

Non. Pas de XAML [lors de l'utilisation de WPF].

11
Alun Harford

Oui, vous pouvez le faire par le ObjectDataProvider. Il vous permet d'appeler un constructeur non par défaut, par exemple:

<Grid>
    <Grid.Resources>
        <ObjectDataProvider x:Key="myDataSource"
                            ObjectType="{x:Type local:Person}">
            <ObjectDataProvider.ConstructorParameters>
                <system:String>Joe</system:String>
            </ObjectDataProvider.ConstructorParameters>
        </ObjectDataProvider>
    </Grid.Resources>
    <Label Content="{Binding Source={StaticResource myDataSource}, Path=Name}"></Label>
</Grid>

en supposant que la personne est

public class Person
{
    public Person(string Name)
    {
        this.Name = Name;
    }
    public string Name { get; set; }
}

Malheureusement, vous ne pouvez pas lier le ConstructorParameters. Voir une solution de contournement ici .

4
chviLadislav