2009-05-14 3 views
0

J'ai un UserControl (a) avec un stackpanel qui a son ItemSource défini à une collection. StackPanel contient ensuite un ensemble de UserControl (b) contenant quelques boutons et un contrôle DataGrid. Y a-t-il un moyen pour le code derrière le UserControl (b) d'accéder aux propriétés dans le code derrière le UserControl parent (a).Informations d'accès WPF à partir du contrôle conteneur

Fondamentalement, lorsque UserControl (a) est chargé dans une fenêtre, un paramètre est transmis dans lequel il contient si le formulaire sera considéré comme en lecture seule ou non. Je voudrais lier la visibilité des boutons dans Usercontrol (b) à la propriété readonly dans le codebehind du parent UserControl (a).

Répondre

2

Normalement, avec WPF, je vous suggère d'implémenter le modèle Model-View-ViewModel (voir MSDN).

Avec ce modèle, vous créez un ViewModel avec toutes les données que vous voulez lier. Cela serait défini comme le contexte de données pour (a) usercontrol. Ce contrôle lierait alors tous ses contrôles aux propriétés du datacontext.

Le contrôle utilisateur enfant (b) hériterait de ce datacontext et pourrait donc lier ses contrôles aux mêmes propriétés que (a) utilise. Cela est dû au fait que les datacontexts sont hérités dans l'arborescence logique (et visuelle) jusqu'à ce qu'ils soient remplacés. Donc, pour vous, je voudrais créer un ViewModel qui contient la propriété ReadOnly. Vous pouvez ensuite définir cet objet ViewModel en tant que datacontext pour le (a) usercontrol. Le contrôle (b) usercontrol, puisqu'il se trouve sous la hiérarchie (a) usercontrol, héritera du même datacontext. Cela vous permettra ensuite de lier les contrôles de (b) aux mêmes propriétés que (a) comme indiqué ci-dessous.

<Button IsEnabled="{Binding ReadOnly}" 
    Context="Click me!" 
    Command="{Binding ClickMeCommand}" /> 

Pour définir le datacontext dans la vue code-behind je fais quelque chose comme ce constructeur illustré ci-dessous. MyView est la classe qui hérite de UserControl dans votre instance. Vous n'avez pas besoin du viewmodel comme je l'ai fait, j'utilise Unity pour injecter le viewmodel dans les vues construites automatiquement depuis que j'utilise Prism mais vous pouvez le créer comme un objet normal et l'assigner au datacontext. Notez que j'ai également lié la commande au bouton en utilisant le datacontext car j'expose habituellement ceux via le ViewModel aussi, c'est facile si vous créez une classe wrapper qui implémente ICommand et proxies à un délégué. Voir DelegateCommand blog article ou regardez la classe DelegateCommand dans Prism si vous êtes intéressé. Si pour une raison quelconque, vous surchargez le datacontext, ce qui peut arriver en utilisant une vue maître/détails où vous changez le datacontext de la section détails de la vue pour être l'élément actuellement sélectionné dans la liste, alors vous pouvez toujours accéder au datacontext parent en utilisant une liaison de source relative.

E.g.

<ComboBox Grid.Row="1" Grid.Column="1" x:Name="Unit" IsReadOnly="True" 
     ItemsSource="{Binding Path=DataContext.AvailableUnits, RelativeSource= 
        {RelativeSource Mode=FindAncestor, 
            AncestorType={x:Type Window}}}" 
     DisplayMemberPath="Name" SelectedItem="{Binding Unit}" /> 

Notez la ItemsSource liaison utilise une source par rapport à trouver la fenêtre parent puis se lier à une propriété de celui-ci est datacontext. J'ai également scindé la liaison ItemsSource entre les guillemets sur plusieurs lignes pour plus de clarté ici, mais je ne le fais pas dans votre xaml, je ne suis pas sûr que cela fonctionne (pas essayé de voir si les extensions de balisage sont tolérantes aux espaces).

Questions connexes