2009-01-07 12 views
31

La idea básica detrás de un botón Cancelar es permitir el cierre de su ventana con una tecla de escape.¿Cómo funciona la propiedad WPF Button.IsCancel?

Usted puede establecer la propiedad IsCancel en el botón Cancelar para cierto, haciendo que el botón para cerrar automáticamente el diálogo sin manipular el evento Haga clic Cancelar.

Fuente: Programación de WPF (Griffith, Sells)

lo que este debe trabajar

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

Sin embargo el comportamiento espero que no está funcionando 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(); 
} 
  • es el comportamiento de IsCancel diferente en función de si la ventana es una ventana normal o un diálogo? ¿Funciona IsCancel como se anuncia solo si se ha llamado a ShowDialog?
  • ¿Se requiere un controlador de Click explícito para el botón (con IsCancel configurado en verdadero) para cerrar una ventana en una prensa de Escape?

Respuesta

29

Sí, sólo funciona en los cuadros de diálogo como una ventana normal no tiene el concepto de "cancelar", es el mismo que DialogResult.Cancel regresar de ShowDialog en WinForms.

Si quería cerrar una ventana con el escape se podría agregar un controlador a PreviewKeyDown en la ventana, recogida de si se trata 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(); 
} 
16

podemos tomar una respuesta de Steve da un paso más y creas una propiedad adjunta que proporciona la funcionalidad "escape al cerrar" para cualquier ventana. Escriba la propiedad una vez y úsela en cualquier ventana. Sólo tiene que añadir lo siguiente a la ventana de XAML:

yournamespace:WindowService.EscapeClosesWindow="True" 

Aquí está el código de 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(); 
    } 
} 
+3

Sí. Las propiedades adjuntas todavía no 'hacen clic' instantáneamente en mi cabeza. – Gishu

+0

Funciona muy bien, lo único es que tuve que reemplazar el casting a Window y agregar una verificación más para null como se sugiere aquí - http://stackoverflow.com/questions/10206742/unable-to-cast-object-of-type -microsoft-expression-platform-wpf-instancebuilder, para evitar el error "No se pudo convertir el objeto de tipo 'Microsoft.Expression.Platform.WPF.InstanceBuilders.WindowInstance' para escribir 'System.Windows.Window'" (el proyecto pudo compilar con éxito, pero los errores fueron molestos. Eso es para mi VS 2012 + R #. También tuve que reiniciar VS después de eso. – sarh

6

Esto no está bien es que ... MSDN dice lo siguiente: Cuando se establece el Si la propiedad Cancelar de un botón es verdadera, usted crea un Botón que está registrado con AccessKeyManager. El botón se activa cuando un usuario presiona la tecla ESC. , así que hay un controlador en su código detrás Y usted no necesita ningún propiedades adjuntas ni nada de eso

+2

MSDN no está del todo completo. Vea el código aquí: http://referencesource.microsoft.com/#PresentationFramework/ Framework/System/Windows/Controls/Button.cs, 274 Cuando se presiona un botón, si no hay Command asignado y se establece IsCancel, DialogCancel se ejecuta automáticamente (después de que el controlador OnClick se complete). – Govert

1

Si esto se right.In aplicación de Windows en WPF y AcceptButton botón Cancelar está allí. Pero una cosa es que si configura su visibilidad de control como falsa, entonces no funcionará como se esperaba. Para eso, necesita hacer que la visibilidad sea verdadera en WPF.Por ejemplo: (no está funcionando 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, es necesario que sea:

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

Entonces usted tiene escribir btnClose_Click en el código detrás de archivo:

private void btnClose_Click (object sender, RoutedEventArgs e) 
    { this.Close(); } 
Cuestiones relacionadas