在这个应用程序中,我将一个Menu放在Usercontrol中。
<UserControl>
<Grid>
<Menu x:Name="mainMenu">
<MenuItem Header="File">
<MenuItem Header="Open Analysis">
<MenuItem Header="Load all" />
<MenuItem Header="Select from tracks" />
</MenuItem>
</MenuItem>
</Menu>
</Grid>
</UserControl>
我想将菜单上的所有“点击”事件路由并冒泡到Usercontrol中的单个Click事件。 所以我实施了:
public static readonly RoutedEvent ClickEvent = eventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MenuItem));
public event RoutedEventHandler Click
{
add { AddHandler(ClickEvent, value); }
remove { RemoveHandler(ClickEvent, value); }
}
但是在例外情况下失败了:
{"RoutedEvent Name 'Click' for OwnerType 'System.Windows.Controls.MenuItem'
already used."}
我想这是因为有多个MenuItems ,因此事件是多次注册,所以它第二次想要注册就失败了。
但是,如何以一种良好的主要方式将所有这些事件“捆绑”(如奇异处理程序附加点)到用户控件中的单个事件中?由于某些子菜单由数据库提供,因此是动态建立的。
答案 0 :(得分:3)
除了已经说过的内容之外,我还会研究一个简单的消息传递解决方案。
每次单击任何菜单项时,都可以广播MenuItemClickedMessage
类型的消息。
public class MenuItemClickedMessage
{
public MenuItem MenuItemClicked { get; set; }
}
然后,您可以拥有一个侦听该事件的组件。收到事件后,您可以从MenuItemClicked
属性中提取菜单项并做出相应的反应。
这需要对简单的消息传递解决方案进行一些研究:http://rachel53461.wordpress.com/2011/05/28/switching-between-viewsusercontrols-using-mvvm/
答案 1 :(得分:2)
与直觉相反,您收到的错误不是由于多个菜单项,而是由于Click
事件已经存在。事件注册是静态的,WPF框架已经使用它。
你会如何解决这个问题?
您可以为菜单创建样式;样式可以在WPF中包含EventSetters
。这允许您为容器中的任何菜单项注册单击处理程序:
<Grid>
<Grid.Resources>
<Style TargetType="MenuItem">
<EventSetter Event="Click" Handler="OnMenuItemClick" />
</Style>
</Grid.Resources>
<Menu x:Name="mainMenu">
...
</Menu>
</Grid>
然后在您的处理程序中确保将Handled
属性设置为true
,以停止冒泡:
private void OnMenuItemClick(object sender, RoutedEventArgs e)
{
e.Handled = true;
}
<强>更新强> 您应该考虑不在UserControl上触发“Click”事件,因为这可能是一个设计问题:当有人使用您的UserControl并且在用户控件上触发Click事件时,您需要“点击”,而不是点击在控件内的菜单项上。
考虑使用自定义事件名称,例如MenuItemClick
,您可以在事件参数中提供菜单项的标识符。
答案 2 :(得分:2)
虽然我强烈建议不要这样做,但是如Bas所指出的那样声明一个独特的新事件,你可以简单地重用MenuItem类中现有的RoutedEvent:
public partial class YourUserControl : UserControl
{
...
public event RoutedEventHandler Click
{
add { AddHandler(MenuItem.ClickEvent, value); }
remove { RemoveHandler(MenuItem.ClickEvent, value); }
}
}
答案 3 :(得分:2)
MenuItemClick - 是一个路由事件,并使用RoutedEventArgs.OriginalSource,而不是发件人。这指向最初触发事件的控件。
<Grid>
<Menu x:Name="mainMenu">
<MenuItem Header="File" Click="OnFileMenuItemClicked">
<MenuItem Header="Open Analysis">
<MenuItem Header="Load all" />
<MenuItem Header="Select from tracks" />
</MenuItem>
</MenuItem>
</Menu>
</Grid>
private void OnFileMenuItemClicked(object sender, RoutedEventArgs e)
{
MenuItem item = e.OriginalSource as MenuItem;
if(null != item)
{
// Handle the menuItem click here
}
}