Domanda

Ho fatto un po' di programmazione WPF e una cosa che non ho mai ottenuto è stato lo schema dei comandi.Ogni esempio sembra essere integrato, modifica, taglia, incolla.Qualcuno ha un esempio o un suggerimento sulle migliori pratiche per i comandi personalizzati?

È stato utile?

Soluzione

Ah ah!Una domanda a cui posso rispondere!Innanzitutto, devo dire che personalmente ho trovato più semplice definire e collegare i comandi nel codice piuttosto che in XAML.Mi consente di collegare i gestori per i comandi in modo un po' più flessibile rispetto a un approccio tutto XAML.

Dovresti capire quali comandi vuoi avere e a cosa si riferiscono.Nella mia applicazione, attualmente ho una classe per definire importanti comandi dell'applicazione in questo modo:

public static class CommandBank
{
  /// Command definition for Closing a window
  public static RoutedUICommand CloseWindow { get; private set; }

  /// Static private constructor, sets up all application wide commands.
  static CommandBank()
  {
    CloseWindow = new RoutedUICommand();
    CloseWindow.InputGestures.Add(new KeyGesture(Key.F4, ModifierKeys.Alt));
    // ...
  }

Ora, poiché volevo mantenere il codice tutto insieme, l'utilizzo di un approccio basato solo sul codice per i comandi mi consente di inserire i seguenti metodi nella classe sopra:

/// Closes the window provided as a parameter
public static void CloseWindowExecute(object sender, ExecutedRoutedEventArgs e)
{
  ((Window)e.Parameter).Close();
}

/// Allows a Command to execute if the CommandParameter is not a null value
public static void CanExecuteIfParameterIsNotNull(object sender, CanExecuteRoutedEventArgs e)
{
  e.CanExecute = e.Parameter != null;
  e.Handled = true;
}

Il secondo metodo può anche essere condiviso con altri comandi senza che io debba ripeterlo ovunque.

Dopo aver definito i comandi in questo modo, puoi aggiungerli a qualsiasi parte dell'interfaccia utente.Di seguito, una volta caricata la finestra, aggiungo i collegamenti di comando sia a Window che a MenuItem e quindi aggiungo un collegamento di input alla finestra utilizzando un ciclo per eseguire questa operazione per tutti i collegamenti di comando.Il parametro passato è la finestra stessa, quindi il codice sopra sa quale finestra provare a chiudere.

public partial class SimpleWindow : Window
{
  private void WindowLoaded(object sender, RoutedEventArgs e)
  {
    // ...
    this.CommandBindings.Add(
      new CommandBinding(
        CommandBank.CloseWindow,
        CommandBank.CloseWindowExecute,
        CommandBank.CanExecuteIfParameterIsNotNull));

    foreach (CommandBinding binding in this.CommandBindings)
    {
       RoutedCommand command = (RoutedCommand)binding.Command;
       if (command.InputGestures.Count > 0)
       {
         foreach (InputGesture gesture in command.InputGestures)
         {
           var iBind = new InputBinding(command, gesture);
           iBind.CommandParameter = this;
           this.InputBindings.Add(iBind);
         }
       }
    }

    // menuItemExit is defined in XAML
    menuItemExit.Command = CommandBank.CloseWindow;
    menuItemExit.CommandParameter = this;
    // ...
  }

  // ....
}

Successivamente disporrò anche di gestori di eventi per gli eventi WindowClosing e WindowClosed, ti consiglio di rendere l'effettiva implementazione dei comandi il più piccola e generica possibile.Come in questo caso, non ho provato a inserire codice che tenta di interrompere la chiusura della finestra se sono presenti dati non salvati, ho mantenuto quel codice saldamente all'interno dell'evento WindowClosing.

Fammi sapere se hai domande di follow-up.:)

Altri suggerimenti

Nell'edizione di settembre 2008 della rivista MSDN, Brian Noyes ha pubblicato un eccellente articolo su RoutedCommand/RoutedEvents!!!

Ecco il link:http://msdn.microsoft.com/en-us/magazine/cc785480.aspx

Il problema di XAML è che va bene per i programmi "semplici", ma purtroppo non funziona bene quando vuoi fare cose come le funzioni di condivisione.Supponiamo che tu abbia diverse classi e interfacce utente con comandi che non sono mai stati disabilitati, dovresti scrivere un metodo "CanAlwaysExecute" per ogni finestra o controllo utente!Non è proprio molto ASCIUTTO.

Dopo aver letto diversi blog e provato diverse cose, ho deciso di creare XAML esclusivamente in termini di aspetto, stili, animazioni e trigger.Tutto il mio collegamento di gestori di eventi e comandi è ora nel code-behind.:)

Un altro trucco tra l'altro è l'associazione di input, affinché vengano catturati, il focus deve essere sull'oggetto che contiene le associazioni di input.Ad esempio, per avere una scorciatoia che puoi utilizzare in qualsiasi momento (ad esempio, F1 per aprire la guida), l'associazione di input deve essere impostata sull'oggetto Window, poiché è sempre attivo quando l'app è attiva.L'uso del metodo del codice dovrebbe renderlo più semplice, anche quando inizi a utilizzare UserControls che potrebbero voler aggiungere associazioni di input alla finestra principale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top