2012-12-12 9 views
12

A volte abbiamo usato modi complessi così tante volte, abbiamo dimenticato i modi più semplici per eseguire l'operazione.Come associare un comando in WPF

So come eseguire il binding di comandi, ma utilizzo sempre lo stesso approccio.

Creare una classe che implementa l'interfaccia ICommand e dal modello di vista creo una nuova istanza di tale classe e l'associazione funziona come un incantesimo.

Questo è il codice che ho usato per il legame

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = this;    
     testCommand = new MeCommand(processor); 
    } 

    ICommand testCommand; 

    public ICommand test 
    { 
     get { return testCommand; } 
    } 
    public void processor() 
    { 
     MessageBox.Show("hello world"); 
    } 
} 

public class MeCommand : ICommand 
{ 
    public delegate void ExecuteMethod(); 
    private ExecuteMethod meth; 
    public MeCommand(ExecuteMethod exec) 
    { 
     meth = exec; 
    } 

    public bool CanExecute(object parameter) 
    { 
     return false; 
    } 

    public event EventHandler CanExecuteChanged; 

    public void Execute(object parameter) 
    { 
     meth(); 
    } 
} 

comando, ma io voglio sapere il modo di base per fare questo, nessun terzo dll non nuova creazione della classe. Esegui questo semplice binding di comandi usando una singola classe. Attuali implementazioni di classe dall'interfaccia ICommand e fanno il lavoro.

risposta

13

Prism già fornito Microsoft.Practices.Prism.Commands.DelegateCommand

Non sono sicuro che è considerato come 3rd party. Almeno è ufficiale e documentato su MSDN.

Alcuni comandi di compilazione nativi come copia, incolla implementano l'interfaccia ICommand. IMHO seguendo il principio Aperto (per estensioni)/Chiudi (per modifiche). in modo che possiamo implementare il nostro comando.


Aggiornamento

Come WPF Comandante documentato here, un estratto ...

WPF fornisce una serie di comandi predefiniti. come Cut, BrowseBack e BrowseForward, Play, Stop e Pause.

Se i comandi nelle classi della libreria comandi non soddisfano le esigenze, , è possibile creare i propri comandi. Esistono due modi per creare un comando personalizzato . Il primo è iniziare da zero e implementare l'interfaccia ICommand . L'altro modo e l'approccio più comune, consiste nel creare un RoutedCommand o un RoutedUICommand.

Ho provato il modello RoutedCommand all'inizio e ho finito con l'implementazione di ICommand.

campione XAML vincolante

<CommandBinding Command="{x:Static custom:Window1.CustomRoutedCommand}" 
        Executed="ExecutedCustomCommand" 
        CanExecute="CanExecuteCustomCommand" /> 

RoutedCommand non è differente da RoutedEvent. questo sembra un gestore di eventi 'Clicked' di un pulsante migliore. Serve allo scopo: separare la logica dell'app da View ma richiedere alcuni attributi DependencyProperty o code-behind.

personalmente mi sento più a mio agio con l'implementazione del mio ICommand.

+1

È definitivamente considerato come una terza parte. Non ho alcun tipo di rancore contro la festa di Thirsd. Sto usando GalaSoft MVVM ma voglio conoscere il modo semplice, basilare e reale di farlo. Grazie comunque. – MegaMind

+1

Invisito per essere l'unico ragazzo che sembra aver effettivamente letto la domanda. – psycho

+0

@psycho Commento costruttivo per essere l'unico ragazzo che capisce il mio dolore. :-) – MegaMind

0

Bene, ce l'hai quasi. Assicurati che CanExecute() restituisca true, altrimenti il ​​tuo codice non verrà eseguito. (Penso che lo farà, ma ancora).Assicurarsi inoltre che aggiungono "NotifyPropertyChanged ('yourCommand')" per

public ICommand test 
    { 
     get { return testCommand; } 
     set { testCOmmand = value; NotifyPropertyChanged("test"); } 
    } 

a qui.

In alternativa è possibile eseguire test = new MeCOmmand(); DataContext = this;

+0

Dov'è il metodo che voglio eseguire all'esecuzione di questo comando? e In alternativa si sta dicendo di usare la classe MeCommand, ma non voglio usare alcuna classe personalizzata come ho menzionato. – MegaMind

+0

Come già detto, il sistema di comando è ostacolato da WPF e non è possibile modificarlo. Esistono implementazioni come RelayCommand/DelegateCommand, ma se si desidera utilizzare i comandi, è necessario implementare l'interfaccia ICommand. Semplice come quella. Forse iniziare a utilizzare gli eventi se si desidera l'esecuzione diretta del metodo. –

+0

È Downvote solo perché non ti sei chiarito nella tua domanda. Non buono stile –

1

A giudicare da ciò che si fa, senza correre il codice in VS, il problema è che si chiama InitializeComponent (rendering XAML), quindi impostare la DataContext senza alcun valore essere nel vostro test proprietà e, infine, impostare un membro privato. In che modo l'interfaccia utente dovrebbe notare che il tuo comando non è più null (che era l'ultimo valore trovato nella proprietà)?

Perché non instanciate il Comando pigramente in questo modo:

public ICommand test 
{ 
    get 
    { 
     if(testCommand== null) 
     { 
     testCommand= new MeCommand(processor); 
     } 
     return testCommand; 
    } 
} 

In questo modo ci sarà non appena è richiesto e non hai bisogno di cambiamento di notifica (a meno che non si cambia quel comando in seguito in fase di esecuzione).

A proposito, ci sono un paio di punti dove si ha la sensazione nessun codice viene eseguito nel Comando scenario Binding:

1) CanExecute() restituisce false: basta restituire true o valutare in base al vostro business case .

2) Le condizioni di CanExecute cambiano, in modo che restituisca true, ma non viene chiamato: È possibile collegare il comando con la classe CommandManager, vedere here. Assicurati che 1) sia risolto prima di provare questo. Ciò garantisce che l'interfaccia utente esegua una nuova query su CanExecute piuttosto frequentemente e, se ciò non è ancora sufficiente, chiamare esplicitamente il metodo CommandManager.InvalidateRequerySuggested().

3) Il tuo legame è sbagliato. Modificare il codice vincolante in questo modo:

Command="{Binding Path=test, PresentationTraceSources.TraceLevel=High}" 

Questo spammare la finestra di output ogni volta che il valore del legame è tirata o spinta. Cerca il termine "usando il valore finale". Se è nullo, il tuo Comando non è dove dovrebbe essere (ancora).

+0

La mia associazione va bene, nessun problema al riguardo. Voglio solo sapere come eseguire il bind del comando senza implementare ICommand in un'altra classe e quindi utilizzare quella classe. Nel mio caso il suo MeCommand. – MegaMind

+2

CommandBinding funziona solo con le implementazioni di ICommand. È la convenzione WPF, non può essere aiutato. Probabilmente potresti voler pensare a usare qualcosa come RelayCommand trovato [qui] (http://msdn.microsoft.com/en-us/magazine/dd419663.aspx). Controlla. –

+2

Onestamente, perché minimizzare tutti noi? Pensi che questo aiuti la comunità? –

2

Utilizzare il comando indirizzato nel caso in cui non si desideri creare una nuova classe. ecco un piccolo frammento. Ho creato un comando instradato come Salva e associarlo a comandare vincolante della finestra, alzare il comando dalla button.and voilà! ..... Spero che questo possa aiutare a

public partial class Window1 : Window 
{ 
    public static readonly RoutedCommand Foo = new RoutedCommand(); 

    public Window1() 
    { 
     InitializeComponent(); 
    } 

    void Foo_CanExecute(object sender, CanExecuteRoutedEventArgs e) 
    { 
     // The Window gets to determine if the Foo 
     // command can execute at this time. 
     e.CanExecute = true; 
    } 

    void Foo_Executed(object sender, ExecutedRoutedEventArgs e) 
    { 
     // The Window executes the command logic when the user wants to Foo. 
     MessageBox.Show("The Window is Fooing..."); 
    } 
} 

<Window.CommandBindings> 
<CommandBinding 
    Command="{x:Static local:Window1.Foo}" 
    CanExecute="Foo_CanExecute" 
    Executed="Foo_Executed" 
    /> 

I spero di aver capito bene il tuo problema

PS: La necessità del modello di comando è di disaccoppiare la logica di esecuzione e di invocare il comando. La classe di comando è un modo per incapsulare la logica.

3

Io tendo a utilizzare il framework MVVM light fornito con RelayCommand integrato.

Si aggiunge una proprietà iCommand al vostro modello di vista, quindi assegnare un relaycommand ad esso: -

ICommand ClickMeCommand {get;set;} 
private void InitCommands() 
{ 
    ClickMeCommand = new RelayCommand(()=>HasBeenClicked=true); 
    //or 
    ClickMeCommand = new RelayCommand(ClickMeEvent); 
} 
public void ClickMeEvent() 
{ 
    HasBeenClicked=true; 
} 

In XAML è sufficiente utilizzare normali vincolante: -

<Button Content='Push me' Command='{Binding ClickMeCommand}' /> 
0

Nella finestra WPF costruttore, per collegare una scorciatoia da tastiera, aggiungere semplicemente un'associazione con un delegato e associarla a un gesto chiave.

public YourWindow() //your constructor 
{ 
    ... 
    //bind keyboard command shortcuts 
    InputBindings.Add(new KeyBinding(//add a new key-binding, bind it to your command object which takes a delegate 
     new WindowCommand(this) 
     { 
     ExecuteDelegate = TogglePause //REPLACE TogglePause with your method delegate 
     }, new KeyGesture(Key.P, ModifierKeys.Control))); 
    ... 
} 

Creare una semplice classe WindowCommand che accetta un delegato di esecuzione per attivare qualsiasi metodo impostato su di esso.

public class WindowCommand : ICommand 
{ 
    private MainWindow _window; 
    public Action ExecuteDelegate { get; set; } 

    public WindowCommand(MainWindow window) 
    { 
     _window = window; 
    } 

    public bool CanExecute(object parameter) 
    { 
     return true; 
    } 

    public event EventHandler CanExecuteChanged; 

    public void Execute(object parameter) 
    { 
     if (ExecuteDelegate != null) 
     { 
      ExecuteDelegate(); 
     } 
     else 
     { 
      throw new InvalidOperationException(); 
     } 
    } 
}