2009-05-13 6 views
1

J'essaie d'accéder à un bouton dans un fichier .xaml dans un code derrière le fichier de mon MainWindow.xaml. J'ai essayé d'utiliser x: Class dans le fichier mais quand je l'utilise, le bouton fonctionne mais j'ai beaucoup d'autres erreurs. donc je préfère ne pas utiliser cette méthode.Contrôles d'accès WPF dans <ResourceDictionary>

Existe-t-il d'autres moyens d'accéder aux contrôles dans un modèle avec une classe de la fonction mainWindows?

le code:

<ResourceDictionary xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' 
       xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' 
       xmlns:l="clr-namespace:Avalon.Demo" x:Class="Bildbanken.MainWindow"> 

     <!-- Taggarnas placering under bilderna (Left/ Top/ Right/ Bottom) --> 
         <Label Content="{Binding Type}" Padding="0,5,7,0" HorizontalAlignment="Right" /> 
         <Label Content="{Binding Category}" Padding="7,0,0,0" /> 
         <ListBox Name="ArtInfo" ItemsSource="{Binding Articles}" BorderThickness="0" Background="{TemplateBinding Background}"> 
          <ListBox.ItemTemplate> 
           <DataTemplate> 
            <Grid> 
             <Grid.ColumnDefinitions> 
              <ColumnDefinition Width="115px" /> 
              <ColumnDefinition Width="auto" /> 
             </Grid.ColumnDefinitions> 
             <TextBlock Grid.Column="0" Text="{Binding Artnr}"></TextBlock> 
             <Button HorizontalAlignment="Right" Name="testbutton" Grid.Column="1">--</Button> 
            </Grid> 
           </DataTemplate> 
          </ListBox.ItemTemplate> 
         </ListBox> 
+0

Pourriez-vous préciser POURQUOI essayez-vous de faire référence à un bouton dans un modèle? Je peux me tromper mais dans 99,9% c'est une mauvaise pratique de faire de telles choses dans WPF. – arconaut

Répondre

0

Il est possible d'accéder au contenu d'un datatemplate. Vous pouvez obtenir l'élément racine du modèle comme celui-ci:

UIElement templateRoot = listbox.ItemTemplate.LoadContent() as UIElement; 

À partir de là, vous utilisez le VisualTreeHelper pour trouver un contrôle Button.

Si vous cherchez simplement à gérer le clic du bouton, l'utilisation de RoutedEvents de WPF est une meilleure alternative.

AddHandler(Button.ClickEvent, new RoutedEventHandler(Button_Click)); 

Ceci permet de saisir chaque clic de bouton, quelle que soit la source. Si vous donnez une étiquette au bouton ou quelque chose, vous pouvez le tester pour filtrer seulement les boutons que vous voulez.

0

Vous pouvez spécifier une RoutedCommand que vous pouvez ajouter via CommandBinding à DataTemplate et au bouton. De cette façon, vous pouvez gérer le bouton click/commande d'exécuter par exemple dans le code derrière et n'avez pas besoin de trouver le bouton via le VisualTreeHelper (ou mon tipp serait SomeElement.TryFindResource ("ButtonKey")). Effacer ce que je veux dire ou ai-je mal compris ce que vous voulez faire avec votre bouton?

0

Commencez par créer un fichier .cs dans lequel vous enregistrez vos commandes. Cela pourrait s'appeler MyCommandCollection.cs. Dans cette classe, vous définissez et enregistrez votre RoutedCommand avec:

public static readonly RoutedCommand ButtonPressCommand= new RoutedCommand("ButtonPress", typeof(MyCommandCollection)); 

Vous définissez la commande dans le UserControl ou la fenêtre que vous voulez l'utiliser dans par exemple

<UserControl.CommandBindings> 
    <CommandBinding Command="Commands:MyCommandCollection.ButtonPressCommand" Execute="Execute_ButtonPressCommand" ... /> 
</UserControl.CommandBindings> 

Dans le code-behind de votre UserControl/fenêtre vous implémentez les méthodes de votre commande Execute/CanExecute.

De cette façon, vous pouvez l'utiliser aussi dans un ResourceDictionary, par exemple comme ça:

<Button Command="Commands:MyCommandCollection.ButtonPressCommand" /> 

Ne pas oublier de mettre aussi les espaces de noms de vos « MyCommandCollectionClass.cs » dans la UserControl/fenêtre et la ResourceDictionary, par exemple:

xmlns:Commands="clr-namespace:MyApp.SomeFolder.Commands" 

Espérons que cela aide.

0

Si vous avez besoin de codebehind pour le contenu d'un modèle, c'est généralement une bonne idée de déplacer le contenu du modèle dans un contrôle utilisateur. (Et c'est souvent une bonne idée même lorsque vous n'avez pas besoin de codebehind.)

Cette answer to another question illustre la technique. (La question peut ne pas sembler pertinente, mais la réponse a impliqué la même approche que celle que je préconise ici: cet exemple utilise des modèles hiérarchiques, mais s'applique aussi aux modèles normaux.)

Les commandes utilisateur offrent deux avantages ici. Tout d'abord, ils évitent d'obtenir des fichiers Xaml trop compliqués - il est facile pour les templates de dominer un fichier Xaml si vous laissez leurs corps en ligne plutôt que de les séparer dans leurs propres fichiers. Deuxièmement, vous pouvez utiliser codebehind facilement. Cela dit, je suis d'accord avec les diverses autres réponses ici qui recommandent d'éviter le codebehind en premier lieu. (Je ne suis pas tout à fait d'accord avec leurs solutions spécifiques - j'utilise l'approche basée sur les commandes, mais je n'utilise pas RoutedCommand - J'utilise une implémentation personnalisée de ICommand qui suit un pattern typiquement appelé DelegatingCommand ou RelayCommand.) Mais même alors, Je définis presque toujours les corps de modèles comme des contrôles utilisateur, juste pour simplifier le Xaml.

Questions connexes