Domanda

L'idea di base dietro un pulsante Annulla è abilitare la chiusura della finestra con un tasto Esc.

  

È possibile impostare la proprietà IsCancel su   il pulsante Annulla su true, causando il   Pulsante Annulla per chiudere automaticamente   la finestra di dialogo senza gestire il clic   evento.

Fonte: programmazione WPF (Griffith, Sells)

Quindi dovrebbe funzionare

<Window>
<Button Name="btnCancel" IsCancel="True">_Close</Button>
</Window>

Tuttavia il comportamento che mi aspetto non sta funzionando per me. La finestra principale è la finestra principale dell'applicazione specificata dalla proprietà Application.StartupUri. Ciò che funziona è

<Button Name="btnCancel" IsCancel=True" Click="CloseWindow">_Close</Button>

private void CloseWindow(object sender, RoutedEventArgs) 
{
    this.Close();
}
  • Il comportamento di IsCancel è diverso in base al fatto che la finestra sia una finestra normale o una finestra di dialogo? IsCancel funziona come pubblicizzato solo se ShowDialog è stato chiamato?
  • È necessario un gestore Click esplicito affinché il pulsante (con IsCancel impostato su true) per chiudere una finestra su una pressione di escape?
È stato utile?

Soluzione

Sì, funziona solo nelle finestre di dialogo poiché una finestra normale non ha il concetto di "cancellazione", è lo stesso di DialogResult.Cancel che ritorna da ShowDialog in WinForms.

Se si desidera chiudere una finestra con escape è possibile aggiungere un gestore a PreviewKeyDown nella finestra, selezionare se si tratta di Key.Escape e chiudere il modulo:

public MainWindow()
{
    InitializeComponent();

    this.PreviewKeyDown += new KeyEventHandler(CloseOnEscape);
}

private void CloseOnEscape(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Escape)
        Close();
}

Altri suggerimenti

Possiamo portare la risposta di Steve un ulteriore passo avanti e creare una proprietà collegata che fornisca la "fuga alla chiusura" funzionalità per qualsiasi finestra. Scrivi una volta la proprietà e usala in qualsiasi finestra. Basta aggiungere quanto segue alla finestra XAML:

yournamespace:WindowService.EscapeClosesWindow="True"

Ecco il codice per la proprietà:

using System.Windows;
using System.Windows.Input;

/// <summary>
/// Attached behavior that keeps the window on the screen
/// </summary>
public static class WindowService
{
   /// <summary>
   /// KeepOnScreen Attached Dependency Property
   /// </summary>
   public static readonly DependencyProperty EscapeClosesWindowProperty = DependencyProperty.RegisterAttached(
      "EscapeClosesWindow",
      typeof(bool),
      typeof(WindowService),
      new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnEscapeClosesWindowChanged)));

   /// <summary>
   /// Gets the EscapeClosesWindow property.  This dependency property 
   /// indicates whether or not the escape key closes the window.
   /// </summary>
   /// <param name="d"><see cref="DependencyObject"/> to get the property from</param>
   /// <returns>The value of the EscapeClosesWindow property</returns>
   public static bool GetEscapeClosesWindow(DependencyObject d)
   {
      return (bool)d.GetValue(EscapeClosesWindowProperty);
   }

   /// <summary>
   /// Sets the EscapeClosesWindow property.  This dependency property 
   /// indicates whether or not the escape key closes the window.
   /// </summary>
   /// <param name="d"><see cref="DependencyObject"/> to set the property on</param>
   /// <param name="value">value of the property</param>
   public static void SetEscapeClosesWindow(DependencyObject d, bool value)
   {
      d.SetValue(EscapeClosesWindowProperty, value);
   }

   /// <summary>
   /// Handles changes to the EscapeClosesWindow property.
   /// </summary>
   /// <param name="d"><see cref="DependencyObject"/> that fired the event</param>
   /// <param name="e">A <see cref="DependencyPropertyChangedEventArgs"/> that contains the event data.</param>
   private static void OnEscapeClosesWindowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
   {
      Window target = (Window)d;
      if (target != null)
      {
         target.PreviewKeyDown += new System.Windows.Input.KeyEventHandler(Window_PreviewKeyDown);
      }
   }

   /// <summary>
   /// Handle the PreviewKeyDown event on the window
   /// </summary>
   /// <param name="sender">The source of the event.</param>
   /// <param name="e">A <see cref="KeyEventArgs"/> that contains the event data.</param>
   private static void Window_PreviewKeyDown(object sender, KeyEventArgs e)
   {
      Window target = (Window)sender;

      // If this is the escape key, close the window
      if (e.Key == Key.Escape)
         target.Close();
   }
}

Questo non è del tutto giusto è ... MSDN dice questo: Quando si imposta la proprietà IsCancel di un pulsante su true, si crea un pulsante registrato con AccessKeyManager. Il pulsante viene quindi attivato quando un utente preme il tasto ESC. Quindi hai bisogno di un gestore nel tuo codice dietro E non hai bisogno di alcuna proprietà collegata o qualcosa del genere

Sì, è giusto. Nell'applicazione Windows in WPF AcceptButton e il pulsante Annulla c'è. Ma una cosa è che se si imposta la visibilità del controllo su false, allora non funzionerà come previsto, per cui è necessario rendere la visibilità come vera in WPF. Ad esempio: (non funziona per il pulsante Annulla perché qui la visibilità è falsa)

<Button x:Name="btnClose" Content="Close" IsCancel="True" Click="btnClose_Click" Visibility="Hidden"></Button> 

Quindi, devi farlo:

<Button x:Name="btnClose" Content="Close" IsCancel="True" Click="btnClose_Click"></Button>

Quindi hai scritto btnClose_Click nel codice dietro il file:

private void btnClose_Click (object sender, RoutedEventArgs e)
    { this.Close(); }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top