我们的应用程序基于一堆页面,这些页面只是FrameworkElement
的子类。主窗口维护该堆栈,并使用内置的Close
命令通过简单地将它们从堆栈中弹出来关闭它们。
现在,在某些情况下,被关闭(或弹出堆栈)的元素需要首先进行一些清理。让该页面同时收听Close
事件似乎是正确的选择。
现在,由于该页面实际上会在窗口之前获取事件(Close
命令是通过“冒泡事件”实现的),因此我们认为我们要做的就是在页面上设置命令绑定,然后在处理程序中,将e.Handled
设置为false,它将继续到窗口。
这是页面中的代码({InitializeCommands
从构造函数中调用)...
private void InitializeCommands(){
CommandBindings.Add(
new CommandBinding(ApplicationCommands.Close, Close_Execute, Close_CanExecute)
);
}
private void Close_CanExecute(object sender, CanExecuteRoutedEventArgs e){
// True executes this handler, but blocks the one in the window
// False executes the one in the window, but ignores this one
e.CanExecute = true;
// Doesn't seem to have any effect
e.Handled = false;
}
private void Close_Execute(object sender, ExecutedRoutedEventArgs e){
Console.WriteLine("I want to respond passively!");
// Doesn't seem to have any effect
e.Handled = false;
}
但是,无论我们将该属性设置为什么,该命令都不会将其置于主窗口中。如果我们删除页面中的命令绑定,它将再次起作用,证明该页面正在吞噬命令,而与该属性无关。
那么,您要怎么做才能使页面被动地监听Close
事件?
答案 0 :(得分:0)
是的,CommandBinding吃命令。这是其实现的摘录:
internal void OnExecuted(object sender, ExecutedRoutedEventArgs e)
{
if (!e.Handled)
{
if (e.RoutedEvent == CommandManager.ExecutedEvent)
{
if (this.Executed != null && CheckCanExecute(sender, e))
{
this.Executed(sender, e);
e.Handled = true;
}
}
else if (this.PreviewExecuted != null && CheckCanExecute(sender, e))
{
this.PreviewExecuted(sender, e);
e.Handled = true;
}
}
}
如您所见,如果为CanExecute返回true,则命令将被吃掉。
您可能想看看CompositeCommand。那将是你的小巷。您创建一个绑定到框架的全局CompositeCommand,然后可以将不同的视图附加到该框架。不同的实现可以采用不同的酷方法来确定命令的多个订阅者的行为。即所有必须返回canExecute,任何必须返回,仅进入活动视图,等等。
编辑:CompositeCommand最初是Prism的一部分,但是您可以找到一个独立的实现,也可以从Prism本身中提取一个实现:
https://github.com/PrismLibrary/Prism/blob/master/Source/Prism/Commands/CompositeCommand.cs
答案 1 :(得分:0)
另一个想法是看看AddHandler()方法。让我们为所有子事件添加一个事件处理程序。即为了控制面包屑,我可以这样做:
AddHandler(BreadcrumbSplitButton.ClickEvent,新的RoutedEventHandler(OnBreadcrumbSplitButtonClick));
在BreadCrumb类中,以侦听所有子级BreadcrumbSplitButtons中的ClickEvent。