2014-11-05 2 views
1

MenuItem и ColumnHeader не являются производными от Control. В полной структуре у них есть собственное свойство .Name, но в компактной структуре они этого не делают. В Visual Studio дизайнер форм показывает (Name) и, конечно, я могу получить доступ к этому объекту, используя это имя в коде. Но как я могу получить это имя как строку во время выполнения? Возможно ли это как-то, может быть, методом расширения, который возвращает имя?Как получить название объекта компонента, который не поддерживает свойство .Name

История вопроса заключается в том, что я создаю мобильные приложения для нескольких языков, и чтобы найти текст для всех элементов формы, я использую имя элемента управления как идентификатор.

Here - это тот, у кого такая же проблема и его решение, но мне это не нравится из-за дополнительного усилия, чтобы ввести все имена во второй раз в коде (а также сохранить их при изменениях), после того как они уже были введены визуально в дизайнере. Я должен был сделать это в течение многих существующих MenuItems и ColumnHeaders ...

this.AddMenuToDictionary(this.menuItemOpen, "menuItemOpen"); 
this.AddMenuToDictionary(this.menuItemExit, "menuItemExit"); 

Если действительно нет лучшего решения, чем при использовании такого словаря, по крайней мере, я хотел бы, чтобы заполнить его без жесткого закодированных строк. Могу ли я сделать это во время инициализации формы с помощью отражения?

+0

Я собирался дать вам это же решение. Почему вам это не нравится? Это просто индексирование ссылок ....... –

+0

@ MatíasFidemraizer, я ответил редактированием :) –

+1

Хм, это действительно отстой. Я не думаю, что вы можете получить _'Name'_ во время выполнения, потому что это определяет только имя _variable_, содержащее его. Поэтому я думаю, что идея словаря - лучший способ продвижения вперед. Вы можете немного улучшить его, используя несколько методов расширения, но это не даст вам многого. Я начал писать ответ с помощью Expressions, чтобы удалить магические строки, но похоже, что это тоже не поддерживается! grrr – Rhumborl

ответ

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<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); 
+0

да, мне это нравится :) – Rhumborl

Смежные вопросы