简体   繁体   中英

Can I give controls an index property in C# like in VB?

I've found similar answers to my question before, but not quite to what I'm trying to do...

In Visual Basic (last I used it, in 06/07) there was an "Index" property you could assign to multiple controls with the same name. I used this primarily to loop through controls, ie:

For i = 1 to 500
    picSeat(i).Print "Hello"
Next i

Is there a way to do this in C#? I know there is a .IndexOf() , but would that really help for what I'm doing? I want to have multiple controls with the same name, just different index. If I'm not being clear, please ask, don't downvote .

EDIT: This is a Windows Form Application, and I'm using Visual Studio 2012. I am talking about controls, not arrays/lists; this was possible in VB and I was wondering if it was possible at all in C#. So I want to have, say, 30 seats in a theatre. I want to have each seat represented by a picturebox named "picSeat". VB would let me name several objects the exact same, and would assign a value to a control property "Index". That way, I could use the above loop to print "Hello" in every picture box with only 3 lines of code.

No, this feature does not exist in C#, and was never implemented in the transition from classic VB to VB.Net.

What I normally do instead is put each of the controls in question in a common parent container. The Form itself can work, but if you need to distinguish these from others of the same type a GroupBox or Panel control will work, too. Then, you access the controls like this:

foreach (var picBox in parentControl.Controls.OfType<PictureBox>())
{
   // do something with each picturebox
}

If you want to use a specific control, just write by name:

pictureBox6.SomeProperty = someValue;

If you need to change a specific control determined at run-time, normally this is in response to a user event:

void PictureBox_Click(object sender, EventArgs e)
{
    var picBox = sender As PictureBox;
    if (picBox == null) return;

    //picBox is now whichever box was clicked
    // (assuming you set all your pictureboxes to use this handler)
}

If you really really want the Control Arrays feature, you can do it by adding code to create the array to your form's Load event:

PictureBox[] pictureBoxes = Me.Controls.OfType<PictureBox>().ToArray();

Are we talking WinForms here? I'm not sure, but I don't think you can have multiple controls in winforms with same name. But I vaguely recall doing something similar and the solution was to name them Button_1, Button_2 etc. Then you can iterate through all controls and get your own index.

Beware though that if you want to instanciate a separate control for each seat in a theatre, you might run into some serious performance issues :) I've done something similar to that as well and ended up drawing the whole thing on a canvas and using mouse coordinates to handle the events correctly.

You may want to check out the Uid property of controls.

( http://msdn.microsoft.com/en-us/library/system.windows.uielement.uid(v=vs.110).aspx )

You can access Control through Uid property with the following

private static UIElement FindUid(this DependencyObject parent, string uid)
{
    var count = VisualTreeHelper.GetChildrenCount(parent);
    if (count == 0) return null;

    for (int i = 0; i < count; i++)
    {
        var el = VisualTreeHelper.GetChild(parent, i) as UIElement;
        if (el == null) continue;

        if (el.Uid == uid) return el;

        el = el.FindUid(uid);
        if (el != null) return el;
    }
    return null;
}

And simply use

var control = FindUid("someUid");

I copied code from this post

If you create an indexed dictionary of your user control, it will behave pretty much the same as in VB6, though you'll not see it on the VS C# GUI. You'll have to get around the placement issues manually. Still - and most importantly -, you'll be able to refer to any instance by the index.

The following example is for 3 pieces for clarity, but of course you could automate every step of the process with appropriate loops.

public partial class Form1 : Form
    {
    ...

        Dictionary<int, UserControl1> NameOfUserControlInstance = new Dictionary<int, UserControl1>()
        {
            { 1, new UserControl1 {}},
            { 2, new UserControl1 {}},
            { 3, new UserControl1 {}}
        };

        private void Form1_Load(object sender, EventArgs e)
        {

            NameOfUserControlInstance[1].Location = new System.Drawing.Point(0, 0);
            NameOfUserControlInstance[2].Location = new System.Drawing.Point(200, 0);
            NameOfUserControlInstance[3].Location = new System.Drawing.Point(400, 0);

            Controls.Add(NameOfUserControlInstance[1]);
            Controls.Add(NameOfUserControlInstance[2]);
            Controls.Add(NameOfUserControlInstance[3]);
        }

        ...

    }  

I like using Tags to apply any type of meta data about the controls

for (int i = 0; i< 10; ++i)
{
  Button button = new Button();
  button.Tag = i;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM