ToolStripMenuItem Click 后获得 SourceControl 问题
在一个listbox中,ContextMenuStrip 被绑定了一个多级的ToolStripMenuItem菜单。
经过网上的一些方法,在第一级下可以获得这个菜单所属的控件。但是多级下就获取不到了。
求办法
[解决办法]
试下这个代码,虽然已经实现了你要的功能,还没有做得很完善,有点BUG,不影响简单的使用。
public static class ContextMenuStripHelper
{
public static event ContextMenuStripItemClickedEventHandler ItemClick;
static Dictionary<ContextMenuStrip, ContextMenuStripState> _menus;
public static void InitializeHelper(this ContextMenuStrip menu)
{
if (menu == null)
throw new ArgumentNullException("menu");
if (_menus == null)
_menus = new Dictionary<ContextMenuStrip, ContextMenuStripState>();
if (!_menus.ContainsKey(menu))
{
WireEvents(menu);
_menus.Add(menu, new ContextMenuStripState());
}
}
static void ContextMenuStrip_Disposed(object sender, EventArgs e)
{
ContextMenuStrip menu = (ContextMenuStrip)sender;
UnwireEvents(menu);
_menus.Remove(menu);
}
private static void WireEvents(ContextMenuStrip menu)
{
menu.Opening += ContextMenuStrip_Opening;
menu.ItemClicked += ContextMenuStrip_ItemClick;
menu.Disposed += ContextMenuStrip_Disposed;
WireEvents(menu.Items);
}
private static void WireEvents(ToolStripItemCollection coll)
{
foreach (ToolStripMenuItem item in coll)
{
ToolStripDropDownItem ddi = item as ToolStripDropDownItem;
if (ddi != null)
{
ddi.DropDownItemClicked += ContextMenuStrip_ItemClick;
WireEvents(ddi.DropDownItems);
}
}
}
private static void UnwireEvents(ContextMenuStrip menu)
{
menu.Opening -= ContextMenuStrip_Opening;
menu.ItemClicked -= ContextMenuStrip_ItemClick;
menu.Disposed -= ContextMenuStrip_Disposed;
UnwireEvents(menu.Items);
}
private static void UnwireEvents(ToolStripItemCollection coll)
{
foreach (ToolStripMenuItem item in coll)
{
ToolStripDropDownItem ddi = item as ToolStripDropDownItem;
if (ddi != null)
{
ddi.DropDownItemClicked -= ContextMenuStrip_ItemClick;
UnwireEvents(ddi.DropDownItems);
}
}
}
static void ContextMenuStrip_ItemClick(object sender, ToolStripItemClickedEventArgs e)
{
if (ItemClick != null)
{
ContextMenuStrip menu = sender as ContextMenuStrip;
if (menu == null)
menu = FindContextMenuStrip((ToolStripItem)sender);
if (menu != null)
{
ItemClick(menu, new ContextMenuStripItemClickedEventArgs(e.ClickedItem, _menus[menu].SourceControl));
}
}
}
public static Control GetSourceControl(object context)
{
if (context == null)
throw new ArgumentNullException("context");
var state = GetState(context);
if (state != null) return state.SourceControl;
else return null;
}
private static ContextMenuStripState GetState(object context)
{
if (_menus != null)
{
ContextMenuStrip menu = context as ContextMenuStrip;
if (menu == null && context is ToolStripItem)
menu = FindContextMenuStrip((ToolStripItem)context);
if (menu == null && context is ToolStrip)
menu = FindContextMenuStrip((ToolStrip)context);
if (menu != null)
{
ContextMenuStripState state;
if (_menus.TryGetValue(menu, out state))
return state;
}
}
return null;
}
private static ContextMenuStrip FindContextMenuStrip(ToolStripItem item)
{
return FindContextMenuStrip(item.Owner);
}
private static ContextMenuStrip FindContextMenuStrip(ToolStrip toolStrip)
{
if (toolStrip != null)
{
if (toolStrip is ContextMenuStrip)
return (ContextMenuStrip)toolStrip;
else if (toolStrip is ToolStripDropDown)
return FindContextMenuStrip(((ToolStripDropDown)toolStrip).OwnerItem);
}
return null;
}
private static void ContextMenuStrip_Opening(object sender, CancelEventArgs e)
{
ContextMenuStrip menu = (ContextMenuStrip)sender;
_menus[menu].SourceControl = menu.SourceControl;
}
class ContextMenuStripState
{
public ContextMenuStripState()
{
}
private Control _sourceControl;
public Control SourceControl
{
get { return _sourceControl; }
set { _sourceControl = value; }
}
}
}
public class ContextMenuStripItemClickedEventArgs : ToolStripItemClickedEventArgs
{
public ContextMenuStripItemClickedEventArgs(ToolStripItem item, Control sourceControl)
: base(item)
{
_sourceControl = sourceControl;
}
private Control _sourceControl;
public Control SourceControl
{
get { return _sourceControl; }
}
}
public delegate void ContextMenuStripItemClickedEventHandler(object sender, ContextMenuStripItemClickedEventArgs e);
调用示例
public Form1()
{
InitializeComponent();
ContextMenuStripHelper.InitializeHelper(contextMenuStrip1);
ContextMenuStripHelper.ItemClick += ContextMenuStripHelper_ItemClick;
}
void ContextMenuStripHelper_ItemClick(object sender, ContextMenuStripItemClickedEventArgs e)
{
var source = e.SourceControl;
if (source != null)
Console.WriteLine("Source: {0}#{1}", source.GetType().Name, source.Name);
else
Console.WriteLine("NULL");
}