簡體   English   中英

在 C# 中按名稱獲取 Windows 窗體控件

[英]Get a Windows Forms control by name in C#

我有一個名為myMenuToolStripMenuItem 我怎樣才能像這樣訪問它:

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

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

這是因為我從 XML 文件動態生成 ToolStripMenuItems,並且需要通過動態生成的名稱引用 MenuItems。

使用Control.ControlCollection.Find方法。

試試這個:

this.Controls.Find()
string name = "the_name_you_know";

Control ctn = this.Controls[name];

ctn.Text = "Example...";
Control GetControlByName(string Name)
{
    foreach(Control c in this.Controls)
        if(c.Name == Name)
            return c;

    return null;
}

無視這一點,我重新發明輪子。

假設您有menuStrip對象並且菜單只有一層深,請使用:

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

對於更深的菜單級別,請在語句中添加更多 SelectMany 運算符。

如果要搜索條帶中的所有菜單項,請使用

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

但是,請確保每個菜單都有不同的名稱,以避免重復鍵引發異常。

為避免異常,您可以使用FirstOrDefault而不是SingleOrDefault / Single ,或者如果您可能有Name重復,則只返回一個序列。

使用與Philip Wallace相同的方法,我們可以這樣做:

    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;
    }

例子:

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

我希望它有幫助! :)

this.Controls.Find(name, searchAllChildren)找不到 ToolStripItem 因為ToolStripItem不是控件

  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)); 
        }
     }
  }

最好的方法之一是單行代碼,如下所示:

在此示例中,我們在表單中按名稱搜索所有PictureBox

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

最重要的是find的第二個參數。

如果您確定控件名稱存在,您可以直接使用它:

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

這是運行的實際代碼:

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;
    }
}

與:

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;
}

您可以在 Form 類中使用 find 函數。 如果你想投射 (Label) ,(TextView) ... 等,這樣你就可以使用對象的特殊功能。 它將返回 Label 對象。

(Label)this.Controls.Find(name,true)[0];

name : 表單中搜索項目的項目名稱

true : 搜索所有 Children 布爾值

假設您有Windows.Form Form1作為擁有您創建的菜單的父窗體。 表單的屬性之一被命名為.Menu 如果菜單是通過編程方式創建的,它應該是相同的,並且會被識別為菜單並放置在 Form 的 Menu 屬性中。

在這種情況下,我有一個名為File的主菜單。 File下稱為MenuItem的子菜單包含標簽Open並命名為menu_File_Open 以下工作。 假設你

// 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;

由於您是動態生成它們,因此請在字符串和菜單項之間保留一個映射,以便快速檢索。

// 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>"];

查看 ToolStrip.Items 集合。 它甚至有一個可用的查找方法。

您可以執行以下操作:

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

一個簡單的解決方案是在foreach循環中遍歷Controls列表。 像這樣的東西:

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

所以現在你有了你的迭代器child ,它的類型是Control 現在做你想做的事,我個人在我之前做的一個項目中發現了這個,它為此控件添加了一個事件,如下所示:

child.MouseDown += new MouseEventHandler(dragDown);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM