ALT + F4和IsCancel按钮

时间:2010-11-25 10:55:32

标签: wpf prism

是否可以让 Alt + F4 (以及X关闭按钮+ <system menu> :: Close)触发标记的按钮如IsCancel?我希望它按照 Esc 键的相同方式运行。

注意:我正在使用Prism并且正在RegionBehavior创建对话框,因此我无法直接访问按钮

2 个答案:

答案 0 :(得分:0)

Alt + F4应该触发CloseCommand(RoutedUICommand,属性来自静态类ApplicationCommands)。 如果你为这个命令定义一个CommandBinding,你应该能够对它做出反应(即调用StopCommand或取消其他方式)并将其标记为已处理,否则Window将处理它并关闭。

如果无法做到这一点,您可以从CloseCommand中分离KeyGesture Alt + F4(在应用程序启动时)并将其映射到您取消的其他一些操作。

答案 1 :(得分:0)

我最终通过自定义行为支持此操作,其代码如下所示。我很乐意切换到一个更干净的实现(例如,一个不需要为按钮添加行为的实现),如果有人能想到一个。

关于实施的一些注释(基于Rx):

  • 它假定单击取消按钮将始终导致窗口关闭。如果取消按钮可以取消(可以这么说),那么当窗口关闭时,按钮就不会被点击。
  • 如果按钮以某种方式从窗口中删除(在我们的例子中,不同的内容被交换到一个区域),它将分离行为。
  • 无论窗口是否关闭,单击按钮或删除按钮,都会在序列结束时删除所有事件处理程序。

以下是代码:

public class DialogCancelButtonBehavior : Behavior<Button>
{
    protected override void OnAttached()
    {
        base.OnAttached();

        Button button = AssociatedObject;

        GetWindowAsync(button)
            .SelectMany(window => GetWindowClosed(window))
            .Where(_ => button.IsCancel)
            .TakeUntil(GetButtonClicked(button))
            .TakeUntil(GetButtonUnloaded(button))
            .Subscribe(_ => ClickButton(button));
    }

    private IObservable<Window> GetWindowAsync(Button button)
    {
        var buttonLoaded = Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>(
            h => new RoutedEventHandler(h),
            h => button.Loaded += h,
            h => button.Loaded -= h);

        return button.IsLoaded
            ? Observable.Return(Window.GetWindow(button))
            : buttonLoaded.Take(1).Select(_ => Window.GetWindow(button));
    }

    private IObservable<IEvent<EventArgs>> GetWindowClosed(Window window)
    {
        return Observable.FromEvent<EventHandler, EventArgs>(
            h => new EventHandler(h),
            h => window.Closed += h,
            h => window.Closed -= h);
    }

    private IObservable<IEvent<RoutedEventArgs>> GetButtonClicked(Button button)
    {
        return Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>(
            h => new RoutedEventHandler(h),
            h => button.Click += h,
            h => button.Click -= h);
    }

    private IObservable<IEvent<RoutedEventArgs>> GetButtonUnloaded(Button button)
    {
        return Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>(
            h => new RoutedEventHandler(h),
            h => button.Unloaded += h,
            h => button.Unloaded -= h);
    }

    private void ClickButton(Button button)
    {
        ButtonAutomationPeer peer = 
            (ButtonAutomationPeer)UIElementAutomationPeer.CreatePeerForElement(button);

        IInvokeProvider invokeProv = 
            peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;

        invokeProv.Invoke(); 
    }
}