2010-03-29 6 views
0

J'ai implémenté une classe IComand personnalisée pour l'un de mes boutons. Le bouton est placé dans une page 'MyPage.xaml' mais sa classe ICommand personnalisée est placée dans une autre classe, pas dans le code MyPage derrière. Puis, à partir XAML je veux lier le bouton avec sa classe de commande personnalisée puis je fais:ICommand WPF sur un bouton

MyPage.xaml:

<Page ...> 

     <Page.CommandBindings> 
      <CommandBinding Command="RemoveAllCommand" 
       CanExecute="CanExecute" 
       Executed="Execute" /> 
     </Page.CommandBindings> 

     <Page.InputBindings> 
       <MouseBinding Command="RemoveAllCommand" MouseAction="LeftClick" /> 
     </Page.InputBindings> 

      <...> 
       <Button x:Name="MyButton" Command="RemoveAllCommand" .../> 
      <...> 

    </Page> 

et la classe bouton de commande personnalisé:

// Here I derive from MyPage class because I want to access some objects from 
// Execute method 
public class RemoveAllCommand : MyPage, ICommand 
{ 

    public void Execute(Object parameter) 
    { 
     <...> 
    } 

    public bool CanExecute(Object parameter) 
    { 
     <...> 
    } 


    public event EventHandler CanExecuteChanged 
    { 
     add { CommandManager.RequerySuggested += value; } 
     remove { CommandManager.RequerySuggested -= value; } 
    } 

} 

Mon problème est comment dire MyPage.xaml que les méthodes Execute et CanExecute pour le bouton est dans une autre classe et non le code derrière lequel est placé le bouton. Comment dire ces méthodes sont dans RemoveAllCommand Class dans la page XAML.

Aussi je veux lancer cette commande quand l'événement de clic de souris est produit dans le bouton ainsi je fais une liaison d'entrée, est-ce correct?

Merci

Répondre

1

Puisque vous avez un ICommand, vous pouvez lier au bouton à travers la propriété de commande et le bouton va l'utiliser, à savoir qu'il appellera CanExecute pour activer/désactiver lui-même et la méthode d'exécution lorsque le le bouton est pressé. Il n'y a pas besoin d'une autre liaison d'entrée.

Maintenant, le problème est que le bouton doit trouver la commande. Une solution simple consiste à mettre une instance de la commande dans le DataContext du bouton (ou de ses parents).

Si le DataContext possède une propriété appelée RemoveAll de type RemoveAllCommand, vous pouvez simplement changer votre bouton XAML pour:

<Button Command="{Binding RemoveAll}" .. /> 

et enlever le CommandBinding et InputBinding

+0

Hey, je l'ai fait mais sans succès, j'ai reçu une erreur lors de la construction du projet: Impossible de créer une instance de type RemoveAllCommand. Je l'explique dans ma réponse publiée. – toni

0

Hey, je l'ai fait, mais avec pas de succès, j'ai reçu une erreur lors de la construction du projet: Impossible de créer une instance de type RemoveAllCommand.

Je l'ai fait:

MyPage.xaml (j'ai enlevé CommandBinding et InputBinding de la page):

<Page x:Class="GParts.Pages.MyPage" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes; 
assembly=PresentationFramework.Aero"    
xmlns:Classes="clr-namespace:GParts.Classes" 
xmlns:Pages="clr-namespace:GParts.Pages"> 

<Page.Resources> 
     <...> 
     <Pages:RemoveAllCommand x:Key="RemoveAllCommandInstance"/> 
     <...> 
</Page.Resources> 

<...> 
<Button Command="{Binding RemoveAllCommandInstance}" ...> 
<...> 
</Page> 

Dans la classe ICommand personnalisée J'ai ajouté un constructeur sans paramètres:

public class RemoveAllCommand : MyPage, ICommand 
{ 

    public RemoveAllCommand() { } 

    ... 
} 

Merci.

+1

Ici, le problème est que vous devriez utiliser {StaticResource RemoveAllCommandInstance} pour obtenir la commande. – Timores

0

oK, Merci, demain je vais essayer.

Maintenant, pour éviter les problèmes, j'ai tout déplacé dans RemoveAllCommandClass Class au code derrière MyPage et j'ai fait quelques modifications.

Je 1.- a ajouté à MyPage.xaml:

xmlns: local = "clr-namespace: GParts"

alors je l'ai fait:

<Page.CommandBindings> 
    <CommandBinding Command="{x:Static local:Pages.MyPage._routedCommand}" 
       Executed="Execute" 
       CanExecute="CanExecute"/> 
</Page.CommandBindings> 


<Button Command="{x:Static local:Pages.MyPage._routedCommand}" .../> 

Et tout est ok et travaille.Quand j'appuie sur le bouton, il exécute le background worker (bw) qui est appelé dans la méthode Execute. bw est dans une autre classe. En arrière-plan, j'ai une variable (isRunning) qui indique si le bw est en cours d'exécution. Avant d'exécuter l'événement DoWork, je le mets à true et lorsque bw est terminé, à RunWorkerCompleted, je le mets à false. Donc à partir de CanExecute, je vérifie isRunning dans la classe bw et je mets à true e.canExecute si isRunning est false, et e.canExecute à false si isRunning est vrai. Le bouton est donc automatiquement désactivé par WPF lorsque bw est en cours d'exécution mais lorsque bw se termine, le bouton continue d'être désactivé et ne retourne pas à l'état activé jusqu'à ce que j'appuie à nouveau dessus. Pourquoi WPF ne met-il pas à jour l'état du bouton pour qu'il soit activé lorsque bw se termine jusqu'à ce que j'appuie de nouveau sur le bouton?

Merci.

+0

Vous devez indiquer à WPF que l'état de la commande a changé. Il existe l'événement CanExecuteChanged à cette fin. – Timores