development

C #에서 이름으로 Windows Forms 컨트롤 가져 오기

big-blog 2020. 12. 6. 21:46
반응형

C #에서 이름으로 Windows Forms 컨트롤 가져 오기


"myMenu"라는 ToolStripMenuItem이 있습니다. 어떻게 이렇게 액세스 할 수 있습니까?

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

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

이는 XML 파일에서 ToolStripMenuItems를 동적으로 생성하고 동적으로 생성 된 이름으로 메뉴 항목을 참조해야하기 때문입니다.


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대신 사용 하거나 중복 이있는 경우 시퀀스를 반환 할 수 있습니다 .SingleOrDefaultSingleName


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

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

도움이 되었기를 바랍니다. :)


동적으로 생성하고 있으므로 문자열과 메뉴 항목 사이에 맵을 유지하면 빠른 검색이 가능합니다.

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

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

Assuming you have Windows.Form Form1 as the parent form which owns the menu you've created. One of the form's attributes is named .Menu. If the menu was created programmatically, it should be the same, and it would be recognized as a menu and placed in the Menu attribute of the Form.

In this case, I had a main menu called File. A sub menu, called a MenuItem under File contained the tag Open and was named menu_File_Open. The following worked. Assuming you

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

One of the best way is a single row of code like this:

In this example we search all PictureBox by name in a form

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

Most important is the second paramenter of find.

if you are certain that the control name exists you can directly use it:

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

Have a look at the ToolStrip.Items collection. It even has a find method available.


You can do the following:

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

A simple solution would be to iterate through the Controls list in a foreach loop. Something like this:

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

So now you have your iterator, child, which is of type Control. Now do what you will with that, personally I found this in a project I did a while ago in which it added an event for this control, like this:

child.MouseDown += new MouseEventHandler(dragDown);

You can use find function in your Form class. If you want to cast (Label) ,(TextView) ... etc, in this way you can use special features of objects. It will be return Label object.

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

name: item name of searched item in the form

true: Search all Children boolean value

참고URL : https://stackoverflow.com/questions/1536739/get-a-windows-forms-control-by-name-in-c-sharp

반응형