72 votes

Appel d'un constructeur paramétré depuis XAML

En utilisant 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é ?

0 votes

Jetez un coup d'œil à ma question stackoverflow.com/questions/15735830/

75voto

Raskal Points 311

.NET 4.0 apporte une nouvelle fonctionnalité qui remet en question la réponse - mais apparemment uniquement pour les applications UWP (pas WPF).

x:Arguments Directive

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

0 votes

Bien, je suis content que tu en parles.

33 votes

Pour tous ceux qui sont venus ici en cherchant exactement cette réponse, je vais vous faire gagner du temps car vous allez trouver ce post à la suite : stackoverflow.com/questions/14347181/

6 votes

"En fait, aucun compilateur actuel (WPF, SL, WinRT) ne le prend en charge" - Duncan Matheson. Lié par le commentaire de Kevek, devrait être dans la réponse.

32voto

Mike Strobel Points 6585

L'un des principes directeurs des objets conviviaux XAML est qu'ils doivent être entièrement utilisables avec un constructeur par défaut, c'est-à-dire qu'il n'y a aucun comportement qui n'est accessible qu'en utilisant un constructeur autre que celui par défaut. Pour s'adapter à la nature déclarative de XAML, les paramètres des objets sont spécifiés via des setters de propriété. Il existe également une convention selon laquelle l'ordre dans lequel les propriétés sont définies dans XAML ne doit pas être important.

Il se peut toutefois que vous ayez des considérations particulières qui sont importantes pour votre mise en œuvre mais qui vont à l'encontre de la convention :

  1. Vous pouvez avoir une ou plusieurs propriétés qui doit doit être définie avant que l'objet puisse être utilisé.
  2. Deux ou plusieurs propriétés peuvent s'exclure mutuellement, par exemple, il est absurde de définir à la fois la propriété StreamSource y UriSource d'une image.
  3. Vous pouvez vouloir vous assurer qu'une propriété est sólo défini 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.

Afin de faciliter le traitement de ces cas, la fonction ISupportInitialize est fournie. Lorsqu'un objet est lu et créé à partir de XAML (c'est-à-dire qu'il est analysé), les objets mettant en œuvre l'option ISupportInitialize seront traitées de manière particulière :

  1. Le constructeur par défaut sera appelé.
  2. BeginInit() sera appelé.
  3. Les propriétés seront définies dans l'ordre où elles apparaissent dans la déclaration XAML.
  4. EndInit() s'appelle.

En suivant les appels à BeginInit() y EndInit() vous pouvez gérer toutes les règles que vous souhaitez imposer, y compris l'obligation de définir certaines propriétés. C'est de cette manière que vous devez gérer les paramètres de création, et non en exigeant des arguments de constructeur.

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

10voto

Alun Harford Points 2373

Non. Pas à partir de XAML [lorsqu'on utilise WPF].

9voto

chviLadislav Points 278

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 cette 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 quelques solutions de contournement ici .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X