【问题标题】:dynamically associate a MenuItem with an item in a List将 MenuItem 与 List 中的项目动态关联
【发布时间】:2011-11-30 11:53:18
【问题描述】:

我正在使用 C#,我有一个对象列表,我想在上下文菜单中显示所有对象,每个对象都显示为 MenuItem

当一个MenuItem被点击时,我想在MenuItem_Click()函数中引用关联的对象。

List<MyObject> MyList = new List<MyObject>();
ContextMenu menu = new ContextMenu();

foreach(MyObject o in MyList)
{
     MenuItem item = new MenuItem();
     item.Header = o.Name;
     item.Click += MenuItem_Click;
     menu.Items.add(item);
}

menu.IsOpen=true;

void MenuItem_Click(object sender, RoutedEventArgs e){

    // Assume the 5th MenuItem is clicked, I need to refer to the 5th object in MyList
    // how to do it?

}

【问题讨论】:

    标签: c# .net winforms contextmenu menuitem


    【解决方案1】:

    适合您当前拥有的代码的快速脏 hack:使用 Tag 属性。

    foreach(MyObject o in MyList)
    {
        MenuItem item = new MenuItem();
        item.Header = o.Name;
        item.Tag = o;
        item.Click += MenuItem_Click;
        menu.Items.add(item);
    }
    

    那么你可以这样引用:

    private void MenuItem_Click(object sender, RoutedEventArgs e)
    {
        var myObj = (MyObject)((MenuItem)sender).Tag;
    }
    

    【讨论】:

    • 尽管投了反对票,但该解决方案确实在他提供的框架内回答了 OP 的问题。
    • 这在我的情况下非常有效。我想知道为什么它被认为是“肮脏的”黑客...... Tag 属性不应该做这样的事情吗?
    • @Laz - 该标签作为通用属性存在,AFAIK 自从在 VB 控件中引入它以来,它就被用于此类事情。就个人而言,这不是我的首选方法,我会使用 ListView 进行数据绑定,并将每个 TemplateItem 作为 MenuItem,然后定位一个命令(将绑定的 MyObject 作为 CommandParameter 传递)。如果我有时间,我可能会在今天晚些时候为您发布一个示例。
    【解决方案2】:

    你可以通过

    MenuItem nItem = sender as MenuItem;
    

    【讨论】:

    • 这获取了 MenuItem,OP 想要用于填充 MenuItem 的数据对象。
    【解决方案3】:
    var clickedItem = e.OriginalSource as MenuItem;
    MyObject myObj = MyList.Find(o => o.Name == clickedItem.Header);
    

    【讨论】:

    • 看代码,item.Header == o.Name 所以MyList.Find(o => o.Name == clickedItem.Header);答案已更新
    • @Dave,在我的例子中,这个名字不是一个安全的标识符,但我认为你的想法应该适用于其他情况。
    猜你喜欢
    • 2011-03-05
    • 2013-04-17
    • 2017-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    相关资源
    最近更新 更多