Wpf ALT+;F4和IsCancel按钮

Wpf ALT+;F4和IsCancel按钮,wpf,prism,Wpf,Prism,是否可以让Alt+F4(以及Xclose按钮+::close)触发标记为IsCancel的按钮?我想让它的行为方式与按Esc键相同 注意:我使用的是Prism,对话框是在区域行为中创建的,因此我无法直接访问按钮Alt+F4应触发CloseCommand(RouteDuicCommand,来自静态类ApplicationCommand的属性)。 如果为此命令定义CommandBinding,则应该能够对其作出反应(即调用StopCommand或以其他方式取消),并将其标记为已处理,否则窗口将处理并

是否可以让Alt+F4(以及
X
close按钮+
::close
)触发标记为
IsCancel
的按钮?我想让它的行为方式与按Esc键相同


注意:我使用的是Prism,对话框是在
区域行为中创建的,因此我无法直接访问按钮Alt+F4应触发CloseCommand(RouteDuicCommand,来自静态类ApplicationCommand的属性)。
如果为此命令定义CommandBinding,则应该能够对其作出反应(即调用StopCommand或以其他方式取消),并将其标记为已处理,否则窗口将处理并关闭


如果这是不可能的,您可以从CloseCommand(在应用程序启动时)中分离按键手势Alt+F4,并将其映射到执行取消操作的其他操作。

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

关于实施的一些注意事项(基于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(); 
    }
}
公共类对话框CancelButtonBehavior:行为
{
受保护的覆盖无效附加()
{
base.onatached();
按钮=关联的对象;
GetWindowAsync(按钮)
.SelectMany(窗口=>GetWindowClosed(窗口))
.Where(=>button.IsCancel)
.TakeUntil(GetButtonClicked(按钮))
.TakeUntil(GetButton未加载(按钮))
.订阅(=>ClickButton(按钮));
}
私有IObservable GetWindowAsync(按钮)
{
var buttonLoaded=可观测的FromEvent(
h=>新的路由EventHandler(h),
h=>button.Loaded+=h,
h=>button.Loaded-=h);
返回按钮。已加载
?可观察。返回(窗口。获取窗口(按钮))
:buttonLoaded.Take(1)。选择(=>Window.GetWindow(按钮));
}
私有IObservable GetWindowClosed(窗口窗口)
{
返回可观察的.FromEvent(
h=>新事件处理程序(h),
h=>window.Closed+=h,
h=>window.Closed-=h);
}
私有IObservable GetButtonClicked(按钮)
{
返回可观察的.FromEvent(
h=>新的路由EventHandler(h),
h=>按钮。单击+=h,
h=>按钮。单击-=h);
}
私有IObservable GetButton未加载(按钮)
{
返回可观察的.FromEvent(
h=>新的路由EventHandler(h),
h=>按钮。卸载+=h,
h=>button.unload-=h);
}
私有作废点击按钮(按钮)
{
按钮自动对等=
(ButtonAutomationPeer)UIElementAutomationPeer.CreatePeerForElement(按钮);
IInvokeProvider invokeProv=
作为IInvokeProvider的peer.GetPattern(PatternInterface.Invoke);
invokeProv.Invoke();
}
}

问题在于,创建
窗口的代码完全不知道按钮,因此无法将它们链接起来。