我最终通过一个自定义行为来支持这一点,代码如下。如果有人能想到的话,我非常乐意切换到更干净的实现(例如,不需要向按钮添加行为的实现)。
关于实现(基于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();
}
}