Как работает свойство WPF Button.IsCancel? - PullRequest
32 голосов
/ 07 января 2009

Основная идея кнопки «Отмена» заключается в том, чтобы разрешить закрытие окна нажатием клавиши Escape.

Вы можете установить свойство IsCancel на кнопка Отмена до истины, вызывая Кнопка Отмена для автоматического закрытия диалог без обработки клика событие.

Источник: Программирование WPF (Griffith, Sells)

Так что это должно работать

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

Однако поведение, которое я ожидаю, мне не подходит. Родительское окно - это главное окно приложения, указанное в свойстве Application.StartupUri. Что работает

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

private void CloseWindow(object sender, RoutedEventArgs) 
{
    this.Close();
}
  • Отличается ли поведение IsCancel в зависимости от того, является ли окно обычным окном или диалоговым окном? IsCancel работает как рекламируется, только если был вызван ShowDialog?
  • Требуется ли явный обработчик Click для кнопки (с IsCancel, установленной в true), чтобы закрыть окно при нажатии Escape?

Ответы [ 4 ]

31 голосов
/ 07 января 2009

Да, он работает только в диалоговых окнах, поскольку в обычном окне отсутствует понятие «отмена», оно аналогично DialogResult.Cancel, возвращающемуся из ShowDialog в WinForms.

Если вы хотите закрыть окно с помощью escape, вы можете добавить обработчик PreviewKeyDown в окне, узнать, является ли он Key.Escape, и закрыть форму:

public MainWindow()
{
    InitializeComponent();

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

private void CloseOnEscape(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Escape)
        Close();
}
16 голосов
/ 04 февраля 2009

Мы можем пойти еще дальше и ответить на вопрос Стива и создать прикрепленное свойство, которое обеспечивает функциональность «бежать при закрытии» для любого окна. Напишите свойство один раз и используйте его в любом окне. Просто добавьте в окно XAML следующее:

yournamespace:WindowService.EscapeClosesWindow="True"

Вот код для собственности:

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();
   }
}
6 голосов
/ 01 декабря 2011

Это не совсем верно, правда ... MSDN говорит следующее: когда вы устанавливаете для свойства IsCancel кнопки значение true, вы создаете кнопку, зарегистрированную в AccessKeyManager. Затем кнопка активируется, когда пользователь нажимает клавишу ESC. Так что вам нужен обработчик в вашем коде позади И вам не нужны никакие вложенные свойства или что-то в этом роде

2 голосов
/ 11 июня 2012

Да, это правильно. В Windows приложение в WPF AcceptButton и кнопка отмены есть. Но одна вещь состоит в том, что если вы устанавливаете видимость элемента управления как false, тогда он не будет работать так, как ожидалось. Для этого вам нужно сделать видимость как true в WPF. Например: (кнопка «Отмена» не работает, потому что здесь видимость ложна)

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

Итак, вам нужно сделать это:

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

Тогда вам нужно написать btnClose_Click в коде файла:

private void btnClose_Click (object sender, RoutedEventArgs e)
    { this.Close(); }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...