以下代码显示正常事件和路由事件。在这里,我使用相同的事件名称来解释目的,但实际上我只使用路由事件。
//Normal Event
public event SelectedHandler Selected;
public delegate void SelectedHandler(Object Sender, RoutedEventArgs e);
//Routed Event
public static readonly RoutedEvent SelectedEvent =
EventManager.RegisterRoutedEvent(
"Selected", RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(MyUserControl));
//add remove handlers
public event RoutedEventHandler Selected
{
add { AddHandler(SelectedEvent, value); }
remove { RemoveHandler(SelectedEvent, value); }
}
我正在从几个事件处理程序中提取这些事件,如下所示
private void lstvMyView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//Normal Event Raise
if (Selected != null)
Selected(this, e);
//Routed Event Raise
RoutedEventArgs args = new RoutedEventArgs(SelectedEvent);
RaiseEvent(args);
}
private void lstvMyView_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
//Normal Event Raise
if (Selected != null)
Selected(this, e);
//Routed Event Raise
RoutedEventArgs args = new RoutedEventArgs(SelectedEvent);
RaiseEvent(args);
}
当我处理正常事件时,我能够将两个处理程序的args发送到事件,但在Routed Event中,args将是一个新实例。我想将两个处理程序的args传递给Routed Event。是否有可能实现这一目标?如果是,那么如何?
答案 0 :(得分:11)
首先你不需要这个(并且应该删除它):
//Normal Event
public event SelectedHandler Selected;
public delegate void SelectedHandler(Object Sender, RoutedEventArgs e);
即。您不需要定义单独的“正常”事件,因为您已经使用此声明完成了它:
public event RoutedEventHandler Selected
{
add { AddHandler(SelectedEvent, value); }
remove { RemoveHandler(SelectedEvent, value); }
}
使用上面的代码块,您使用“普通”(clr)“包装”路由事件,以便您的类的用户可以使用“普通”语法(即instanceOfMyUserControl.Selected += ....
)
第二,如果您希望路由事件的事件参数与您正在侦听的SelectionChanged
的{{1}}事件的事件参数相同,则应声明此路由事件方式:
ListView
请注意,我已将public static readonly RoutedEvent SelectedEvent =
EventManager.RegisterRoutedEvent(
"Selected", RoutingStrategy.Bubble,
typeof(SelectionChangedEventHandler),
typeof(MyUserControl));
//add remove handlers
public event SelectionChangedEventHandler Selected
{
add { AddHandler(SelectedEvent, value); }
remove { RemoveHandler(SelectedEvent, value); }
}
替换为RoutedEventHandler
,因为它是可以“携带”SelectionChangedEventHandler
的预定义的。{/ p>
现在为了事件的兴起。 你不需要同时升级“正常”和路由(因为“正常”是路由的包装),所以你应该删除它:
SelectionChangedEventArgs
并且只提升路由版本,可以这样做:
//Normal Event Raise
if (Selected != null)
Selected(this, e);
请注意,我使用原始事件中的事件参数来设置一个自定义事件的SelectionChangedEventArgs args =
new SelectionChangedEventArgs(SelectedEvent, e.RemovedItems, e.AddedItems);
RaiseEvent(args);
和AddedItems
。
答案 1 :(得分:0)
要继续你的最后评论(可以给出一个特定评论的链接吗?)我会写另一个答案,以便人们可以关注。
我认为你完全忽略了事件的重点。您希望事件的处理程序在收到它时知道什么?这通常是事件参数的目的 - 您将一些信息传递给处理程序,您可以使用该处理程序了解确切发生的事情。
所以,当你第一次举办活动时,你会这样做:
private void lstvMyView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SelectionChangedEventArgs args =
new SelectionChangedEventArgs(SelectedEvent, e.RemovedItems, e.AddedItems);
RaiseEvent(args);
}
首先必须构造参数,然后将RaiseEvent()
函数与该参数一起使用,因为您想要引发wpf的特殊路由类型的事件。参数必须是继承RoutedEventArgs的类的实例。请注意,您构建的SelectionChangedEventArgs
是在wpf中定义的,以便将“附加”信息“携带”到事件的处理程序中 - 即哪些项目已从选择中删除,哪些项目已添加,因此当处理程序收到事件时它可以根据需要使用该信息。
关于这个想你正在做的事情:
//Normal Event Raise
if (Selected != null)
Selected(this, e);
基本上 - (正如我在第一个回答中所说)删除它,你不需要它。
所以困扰你的是你第二次举起这个活动。这是你必须做的原型:
private void lstvMyView_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
SelectionChangedEventArgs args =
new SelectionChangedEventArgs(SelectedEvent, ?, ?);
RaiseEvent(args);
}
如您所见,您必须再次构建SelectionChangedEventArgs
并使用RaiseEvent()
函数来引发事件。但是这次你不能使用e.RemovedItems
和e.AddedItems
,因为你正在处理一个MouseLeftButtonUp
事件,它(通过它的args)包含有关鼠标状态的信息 - 而不是添加了哪些项目选择(在所有鼠标事件之后,而不是选择事件)。
您必须决定更换两个问号的内容 - 正如我在第一个答案的评论中所说,您必须决定要向您的活动用户传达哪些信息。什么意味着“lstvMyView”上的鼠标按钮不再显示?最简单的事情就是:
SelectionChangedEventArgs args =
new SelectionChangedEventArgs(SelectedEvent, Enumerable.Empty<object>(), Enumerable.Empty<object>());
RaiseEvent(args);
您正在筹集活动并告知其消费者没有从选择中删除任何项目且未添加任何项目。