MenuItem
和ColumnHeader
不是来自Control
。在完整的框架中,它们具有自己的.Name
属性,但在紧凑的框架中它们没有。在Visual Studio中,表单设计器显示(Name)
,当然我可以在代码中使用此名称访问该对象。但是如何在运行时将该名称作为字符串?是否有可能通过一个返回名称的扩展方法?
背景是我正在创建多语言Windows移动应用程序,并且为了查找表单上所有项目的文本,我使用控件的名称作为标识符。
Here是有同样问题的人和他的解决方案,但我不喜欢它,因为他们需要额外努力在代码中再次输入所有名称(并在更改时保留它们)已经在设计师中直观地输入了。我必须为许多现有的MenuItems和ColumnHeaders ......
做这件事this.AddMenuToDictionary(this.menuItemOpen, "menuItemOpen");
this.AddMenuToDictionary(this.menuItemExit, "menuItemExit");
如果没有比使用这样的字典更好的解决方案,至少我想在没有硬编码字符串的情况下填写它。我可以在使用反射初始化表单时执行此操作吗?
答案 0 :(得分:1)
如果您可以访问表单,而不仅仅是MenuItem
对象本身,那么很容易:
foreach (FieldInfo fi in form.GetType().GetFields(
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly))
if (fi.FieldType.Name == "MenuItem")
{
var mi = (MenuItem) fi.GetValue(form);
mi.Text = Translate(fi.ReflectedType.Namespace,
fi.ReflectedType.Name + '.' + fi.Name, fi.FieldType.Name, mi.Text);
}
非常欢迎任何改进,请发表评论或创建更好的答案。
对于表单中的所有控件,也可以更普遍地执行此操作,或者可能仅针对不是从Control
派生的组件。通过反射,我们甚至不必转换为特定类型(如上所述),我们可以只查找Text属性的存在并进行翻译。
但是因为我想构建包含子菜单层次结构的标识符,所以我决定回到Dictionary方法并递归循环遍历项目(短伪代码):
Dictionary<Component, string> ComponentNames;
foreach (FieldInfo fi in form.GetType().GetFields(
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly))
if (fi.FieldType.Name == "MenuItem" || fi.FieldType.Name == "ColumnHeader")
ComponentNames.Add((Component) fi.GetValue(form), fi.Name);
void Recurse(Menu menu, string strIdentifier) {
if (ComponentNames.TryGetValue(menu, out strName))
Translate(strIdentifer += '.' + strName, ref strText);
foreach (MenuItem mi in menu.MenuItems) Recurse(mi, strIdentifier);