Pregunta

La idea básica detrás de un botón Cancelar es habilitar el cierre de la ventana con una pulsación de tecla Escape.

  

Puedes establecer la propiedad IsCancel en   el botón Cancelar a verdadero, causando la   Botón de cancelar para cerrar automáticamente   El diálogo sin manejar el clic.   evento.

Fuente: Programación WPF (Griffith, Sells)

Así que esto debería funcionar

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

Sin embargo, el comportamiento que espero no funciona para mí. La ventana principal es la ventana principal de la aplicación especificada por la propiedad Application.StartupUri. Lo que funciona es

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

private void CloseWindow(object sender, RoutedEventArgs) 
{
    this.Close();
}
  • ¿El comportamiento de IsCancel es diferente en función de si la ventana es una ventana normal o un diálogo? ¿IsCancel funciona como se anuncia solo si se ha llamado a ShowDialog?
  • ¿Se requiere un controlador de clic explícito para que el botón (con IsCancel configurado en verdadero) cierre una ventana en una pulsación de Escape?
¿Fue útil?

Solución

Sí, solo funciona en los cuadros de diálogo, ya que una ventana normal no tiene el concepto de " cancelar " ;, es lo mismo que DialogResult.Cancel que regresa de ShowDialog en WinForms.

Si desea cerrar una ventana con escape, puede agregar un controlador a PreviewKeyDown en la ventana, seleccionar si es Key.Escape y cerrar el formulario:

public MainWindow()
{
    InitializeComponent();

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

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

Otros consejos

Podemos llevar la respuesta de Steve un paso más allá y crear una propiedad adjunta que proporcione el " escape on close " Funcionalidad para cualquier ventana. Escriba la propiedad una vez y utilícela en cualquier ventana. Simplemente agregue lo siguiente a la ventana XAML:

yournamespace:WindowService.EscapeClosesWindow="True"

Aquí está el código para la propiedad:

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();
   }
}

Esto no está bien, ¿verdad? MSDN dice esto: cuando establece la propiedad IsCancel de un botón en verdadero, crea un botón que está registrado con AccessKeyManager. El botón se activa cuando un usuario presiona la tecla ESC. Así que necesitas un controlador en tu código detrás Y no necesitas ninguna propiedad adjunta ni nada de eso

Sí, esto es correcto. En la aplicación de Windows en WPF AcceptButton y el botón Cancelar está ahí. Pero una cosa es que si está configurando su visibilidad de control como falsa, entonces no funcionará como se esperaba. Para eso, debe hacer que la visibilidad sea verdadera en WPF. Por ejemplo: (no funciona para el botón Cancelar porque aquí la visibilidad es falsa)

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

Por lo tanto, necesita hacerlo:

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

Luego tienes que escribir btnClose_Click en el código detrás del archivo:

private void btnClose_Click (object sender, RoutedEventArgs e)
    { this.Close(); }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top