2009-10-08 33 views
44

Tôi có một ToolStripMenuItem được gọi là "myMenu". Làm thế nào tôi có thể truy cập này như sau:Kiểm soát Windows Forms bằng tên trong C#

/* Normally, I would do: */ 
this.myMenu... etc. 

/* But how do I access it like this: */ 
String name = myMenu; 
this.name... 

Điều này là do tôi tự động tạo ra ToolStripMenuItems từ một file XML và cần phải tham khảo menuitems bằng tên tự động tạo ra của họ.

Trả lời

84

Sử dụng phương pháp Control.ControlCollection.Find.

Hãy thử điều này:

this.Controls.Find() 
+3

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.controlcollection .find% 28VS.80% 29.aspx – RvdK

+1

Điều này làm việc hoàn hảo nhờ –

+1

Điều này không hiệu quả đối với tôi. Tôi nghĩ bởi vì, như o3o đã chỉ ra, một ToolStripMenuItem không phải là một điều khiển. – Luca

8
Control GetControlByName(string Name) 
{ 
    foreach(Control c in this.Controls) 
     if(c.Name == Name) 
      return c; 

    return null; 
} 

Coi thường này, tôi tái bánh xe.

+0

Thêm một giải pháp đa mục đích-ish hơn của Julien. Vẫn hoạt động tốt mặc dù. –

+0

Giải pháp tuyệt vời, đây là những gì tôi đang tìm kiếm thời gian dài. Cảm ơn! :) – Vikyboss

+2

Mục đích chung-ish là tốt! +1 –

3

Vì bạn đang tạo chúng động, hãy giữ bản đồ giữa một chuỗi và mục menu, điều này sẽ cho phép truy xuất nhanh.

// in class scope 
private readonly Dictionary<string, ToolStripMenuItem> _menuItemsByName = new Dictionary<string, ToolStripMenuItem>(); 

// in your method creating items 
ToolStripMenuItem createdItem = ... 
_menuItemsByName.Add("<name here>", createdItem); 

// to access it 
ToolStripMenuItem menuItem = _menuItemsByName["<name here>"]; 
+1

Bây giờ CÓ MỘT ý tưởng! +1 (mặc dù chỉ hoạt động nếu điều khiển đã có trong từ điển) –

0

Hãy xem bộ sưu tập ToolStrip.Items. Nó thậm chí có một phương pháp tìm kiếm có sẵn.

0

Bạn có thể làm như sau:

 
private ToolStripMenuItem getToolStripMenuItemByName(string nameParam) 
    { 
     foreach (Control ctn in this.Controls) 
     { 
      if (ctn is ToolStripMenuItem) 
       { 
        if (ctn.Name = nameParam) 
         { 
         return ctn; 
         } 
       } 
     } 
     return null; 
    } 
28
string name = "the_name_you_know"; 

Control ctn = this.Controls[name]; 

ctn.Text = "Example..."; 
+0

vấn đề duy nhất với ToolStripMenuItem là nó không phải là một điều khiển và mã của bạn sẽ không hoạt động. ; ( – dmihailescu

+1

Thực ra câu trả lời này gần hơn với câu hỏi đối với tôi. – TechNyquist

3
this.Controls["name"]; 

Đây là mã thực tế đó là ran:

public virtual Control this[string key] 
{ 
    get 
    { 
     if (!string.IsNullOrEmpty(key)) 
     { 
      int index = this.IndexOfKey(key); 
      if (this.IsValidIndex(index)) 
      { 
       return this[index]; 
      } 
     } 
     return null; 
    } 
} 

vs:

public Control[] Find(string key, bool searchAllChildren) 
{ 
    if (string.IsNullOrEmpty(key)) 
    { 
     throw new ArgumentNullException("key", SR.GetString("FindKeyMayNotBeEmptyOrNull")); 
    } 
    ArrayList list = this.FindInternal(key, searchAllChildren, this, new ArrayList()); 
    Control[] array = new Control[list.Count]; 
    list.CopyTo(array, 0); 
    return array; 
} 

private ArrayList FindInternal(string key, bool searchAllChildren, Control.ControlCollection controlsToLookIn, ArrayList foundControls) 
{ 
    if ((controlsToLookIn == null) || (foundControls == null)) 
    { 
     return null; 
    } 
    try 
    { 
     for (int i = 0; i < controlsToLookIn.Count; i++) 
     { 
      if ((controlsToLookIn[i] != null) && WindowsFormsUtils.SafeCompareStrings(controlsToLookIn[i].Name, key, true)) 
      { 
       foundControls.Add(controlsToLookIn[i]); 
      } 
     } 
     if (!searchAllChildren) 
     { 
      return foundControls; 
     } 
     for (int j = 0; j < controlsToLookIn.Count; j++) 
     { 
      if (((controlsToLookIn[j] != null) && (controlsToLookIn[j].Controls != null)) && (controlsToLookIn[j].Controls.Count > 0)) 
      { 
       foundControls = this.FindInternal(key, searchAllChildren, controlsToLookIn[j].Controls, foundControls); 
      } 
     } 
    } 
    catch (Exception exception) 
    { 
     if (ClientUtils.IsSecurityOrCriticalException(exception)) 
     { 
      throw; 
     } 
    } 
    return foundControls; 
} 
4

this.Controls.Find (tên, searchAllChildren) không tìm ToolStripItem vì ToolStripItem không phải là một điều

using SWF = System.Windows.Forms; 
    using NUF = NUnit.Framework; 
    namespace workshop.findControlTest { 
    [NUF.TestFixture] 
    public class FormTest { 
     [NUF.Test]public void Find_menu() { 
      // == prepare == 
      var fileTool = new SWF.ToolStripMenuItem(); 
      fileTool.Name = "fileTool"; 
      fileTool.Text = "File"; 

      var menuStrip = new SWF.MenuStrip(); 
      menuStrip.Items.Add(fileTool); 

      var form = new SWF.Form(); 
      form.Controls.Add(menuStrip); 

      // == execute == 
      var ctrl = form.Controls.Find("fileTool", true); 

      // == not found! == 
      NUF.Assert.That(ctrl.Length, NUF.Is.EqualTo(0)); 
     } 
    } 
    } 
5

Giả sử bạn có đối tượng menuStrip và trình đơn này chỉ có một mức độ sâu sắc, sử dụng:

ToolStripMenuItem item = menuStrip.Items 
    .OfType<ToolStripMenuItem>() 
    .SelectMany(it => it.DropDownItems.OfType<ToolStripMenuItem>()) 
    .SingleOrDefault(n => n.Name == "MyMenu"); 

Để biết cấp độ menu sâu hơn, hãy thêm các toán tử SelectMany khác vào câu lệnh.

nếu bạn muốn tìm kiếm tất cả các mục trình đơn trong dải sau đó sử dụng

ToolStripMenuItem item = menuStrip.Items 
    .Find("MyMenu",true) 
    .OfType<ToolStripMenuItem>() 
    .Single(); 

Tuy nhiên, chắc chắn rằng mỗi menu có một cái tên khác nhau để tránh ném ngoại lệ bởi bản sao chìa khóa.

Để tránh ngoại lệ, bạn có thể sử dụng FirstOrDefault thay vì SingleOrDefault/Single hoặc chỉ trả lại chuỗi nếu bạn có thể có Name trùng lặp.

2

Giả sử bạn có Windows.Form Form1 làm biểu mẫu gốc sở hữu menu bạn đã tạo. Một trong các thuộc tính của biểu mẫu có tên là .Menu. Nếu trình đơn được tạo lập trình, nó sẽ giống nhau và nó sẽ được nhận dạng như một trình đơn và được đặt trong thuộc tính Menu của Biểu mẫu.

Trong trường hợp này, tôi có một menu chính có tên là File. Một menu phụ, được gọi là MenuItem dưới File chứa thẻ Open và được đặt tên là menu_File_Open. Sau đây đã làm việc. Giả sử bạn

// So you don't have to fully reference the objects. 
using System.Windows.Forms; 

// More stuff before the real code line, but irrelevant to this discussion. 

MenuItem my_menuItem = (MenuItem)Form1.Menu.MenuItems["menu_File_Open"]; 

// Now you can do what you like with my_menuItem; 
0

Một giải pháp đơn giản có thể lặp qua danh sách Controls trong một vòng lặp foreach. Một cái gì đó như thế này:

foreach (Control child in Controls) 
{ 
    // Code that executes for each control. 
} 

Vì vậy, bây giờ bạn có iterator của bạn, child, mà là loại Control. Bây giờ làm những gì bạn sẽ với điều đó, cá nhân tôi thấy điều này trong một dự án tôi đã làm một thời gian trước, trong đó nó thêm một sự kiện để kiểm soát này, như thế này:

child.MouseDown += new MouseEventHandler(dragDown); 
1

Sử dụng phương pháp tương tự của Philip Wallace, chúng ta có thể làm như thế này:

public Control GetControlByName(Control ParentCntl, string NameToSearch) 
    { 
     if (ParentCntl.Name == NameToSearch) 
      return ParentCntl; 

     foreach (Control ChildCntl in ParentCntl.Controls) 
     { 
      Control ResultCntl = GetControlByName(ChildCntl, NameToSearch); 
      if (ResultCntl != null) 
       return ResultCntl; 
     } 
     return null; 
    } 

Ví dụ:

public void doSomething() 
    { 
      TextBox myTextBox = (TextBox) this.GetControlByName(this, "mytextboxname"); 
      myTextBox.Text = "Hello!"; 
    } 

tôi hy vọng nó giúp đỡ! :)

0

Một trong những cách tốt nhất là một hàng duy nhất của mã như thế này:

Trong ví dụ này, chúng tôi tìm kiếm tất cả PictureBox theo tên trong một hình thức

PictureBox[] picSample = 
        (PictureBox)this.Controls.Find(PIC_SAMPLE_NAME, true); 

Quan trọng nhất là paramenter thứ hai của find.

nếu bạn chắc chắn rằng tên kiểm soát tồn tại, bạn có thể trực tiếp sử dụng nó:

PictureBox picSample = 
         (PictureBox)this.Controls.Find(PIC_SAMPLE_NAME, true)[0]; 
Các vấn đề liên quan