Pergunta

Eu fiz alguma programação WPF e uma coisa que nunca entendi foi o padrão de comando.Cada exemplo parece ser incorporado, editar, cortar, colar.Alguém tem um exemplo ou sugestão de práticas recomendadas para comandos personalizados?

Foi útil?

Solução

Ah, ah!Uma pergunta que posso responder!Em primeiro lugar, devo mencionar que pessoalmente achei mais fácil definir e conectar comandos em código do que em XAML.Isso me permite conectar os manipuladores para os comandos com um pouco mais de flexibilidade do que uma abordagem totalmente XAML.

Você deve descobrir quais comandos deseja ter e com o que eles se relacionam.No meu aplicativo, atualmente tenho uma classe para definir comandos importantes do aplicativo, como este:

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));
    // ...
  }

Agora, como eu queria manter o código todo unido, usar uma abordagem somente de código para Comandos me permite colocar os seguintes métodos na classe acima:

/// 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;
}

O segundo método pode até ser compartilhado com outros Comandos sem que eu precise repeti-lo em todos os lugares.

Depois de definir os comandos como este, você pode adicioná-los a qualquer parte da IU.A seguir, depois que a janela for carregada, adiciono ligações de comando a Window e MenuItem e, em seguida, adiciono uma ligação de entrada à janela usando um loop para fazer isso para todas as ligações de comando.O parâmetro passado é a própria janela, para que o código acima saiba qual janela tentar fechar.

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;
    // ...
  }

  // ....
}

Mais tarde, também tenho manipuladores de eventos para os eventos WindowClosing e WindowClosed. Recomendo que você torne a implementação real dos comandos tão pequena e genérica quanto possível.Como neste caso, não tentei colocar um código que tente impedir o fechamento da janela se houver dados não salvos, mantive esse código firmemente dentro do evento WindowClosing.

Deixe-me saber se você tiver alguma dúvida de acompanhamento.:)

Outras dicas

Na edição de setembro de 2008 da revista MSDN, Brian Noyes tem um excelente artigo sobre RoutedCommand/RoutedEvents!!!

Aqui está o link:http://msdn.microsoft.com/en-us/magazine/cc785480.aspx

O problema do XAML é que ele é adequado para programas 'simples', mas, infelizmente, não funciona bem quando você deseja fazer coisas como compartilhar funções.Digamos que você tenha várias classes e interfaces de usuário, todas com comandos que nunca foram desabilitados, você teria que escrever um método 'CanAlwaysExecute' para cada janela ou UserControl!Isso não é muito SECO.

Depois de ler vários blogs e tentar diversas coisas, optei por tornar o XAML puramente baseado em aparência, estilos, animação e gatilhos.Toda a minha conexão de manipuladores de eventos e comandos agora está no code-behind.:)

Outra pegadinha, a propósito, é a ligação de entrada; para que sejam capturadas, o foco deve estar no objeto que contém as ligações de entrada.Por exemplo, para ter um atalho que você possa usar a qualquer momento (digamos, F1 para abrir a ajuda), essa ligação de entrada deve ser definida no objeto Window, pois ele sempre terá foco quando seu aplicativo estiver ativo.Usar o método de código deve tornar isso mais fácil, mesmo quando você começa a usar UserControls que podem querer adicionar ligações de entrada à janela pai.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top