【问题标题】:Making an indexed control array?制作索引控件数组?
【发布时间】:2012-07-22 04:28:19
【问题描述】:

是否有 C# 索引控件数组?我想放置一个“按钮数组”,例如带有 5 个按钮,它们只使用一个事件处理程序来处理所有这 5 个控件的索引(就像 VB6 一样)。否则我必须为这 5 个按钮中的每一个编写一个额外的事件处理程序。如果我有 100 个按钮,我需要 100 个事件处理程序吗?我的意思是这样的:

TextBox1[i].Text="Example";

它可以让我使用控制数组更轻松地进行编码。现在我已经看到,C# 至少在用户控件上没有可见的数组功能,并且在用户控件上没有“索引”属性。所以我猜 C# 没有控制数组,或者我必须用已知名称调用每个元素。

我必须这样写:

TextBox1.Text = Value1;
TextBox2.Text = Value2;
...
...
TextBox100.Text = Value100;

更多的工作 + 所有这 100 个事件处理程序,每一个都额外增加一个 TextBox。

【问题讨论】:

  • 每个父控件都有一个属性.Controls,它可以访问子控件的集合。如果您将所有文本框/按钮放在同一个父容器中,则可以通过子控件列表引用它们。
  • 您可以将同一个事件处理程序分配给多个控件,您不需要为每个控件实例创建新的事件处理程序实现。
  • 你可能有一些运气实现 ICollection where T : Control,但你不能将事件处理程序添加到数组中。
  • 您不能使用反射(一次)将所有控件放入一个数组中,然后将其用作数组吗?当然 - 如果您只是在事件处理程序之后,还有其他建议的方法。
  • 用户的负担反复暴露在一百个文本框的 UI 灾难中,需要与程序员应得的炼狱相匹配。这是唯一的公平。

标签: c# arrays winforms user-controls


【解决方案1】:

我知道我参加这个聚会有点晚了,但这个解决方案会奏效:

制作一个全局数组:

    TextBox[] myTextBox;

然后在你的对象的构造函数中,在调用之后

    InitializeComponent();

初始化你的数组:

    myTextBox = new TextBox[] {TextBox1, TextBox2, ... };

现在您可以迭代控件数组:

    for(int i = 0; i < myTextBox.Length; i++)
        myTextBox[i].Text = "OMG IT WORKS!!!";

我希望这会有所帮助!

皮特

【讨论】:

    【解决方案2】:

    正如我在对 HatSoft 解决方案的评论中提到的,C# Winforms 不允许您像旧的 VB6 允许我们创建控件数组。我认为我们能得到的最接近的是 HatSoft 和 Bert Evans 在他们的帖子中展示的内容。

    我希望能满足您的要求的一件事是事件处理程序,您将获得一个通用事件处理程序,并且在事件处理程序中,当您对“发送者”进行类型转换时,您可以直接获得控件,就像在 VB6 中一样

    C#

    TextBox textBox = sender as TextBox;
    

    VB6

    TextBox textBox = TextBox1[i];
    

    因此,您可能遇到的唯一麻烦是将这 100 个文本框连接到单个事件处理程序,如果您不是通过代码动态创建控件,而是在设计时手动创建它,那么所有人都可以建议将它们分组在一个容器中,例如说面板。然后在 Form Load 上将它们全部连接到一个事件处理程序,如下所示:

    foreach (Control control in myTextBoxPanel.Controls)
    {
        if(control is TextBox)
             control.TextChanged += new EventHandler(control_TextChanged);
    }
    

    【讨论】:

      【解决方案3】:

      只需创建一个处理程序并将所有按钮指向它。

      var ButtonHandler = (sender, args) => {
          var clicked = (Button)sender;
          if (clicked.Text == "whatever")
             //do stuff
          else
             //do other stuff 
      };
      
      button1.Click += ButtonHandler;
      button2.Click += ButtonHandler;
      

      或者,如果您在代码中创建控件,您可以使用one of the techniques specified in this answer

      【讨论】:

      • 啊,你提到了用户控件,我一下子得出了结论。
      • 底线,创建单个事件处理程序,并将其分配给控件事件。
      • @feedwall 处理程序接收发送者作为参数。如果为每个控件分配一个值,则可以检查该值以确定单击了哪个控件。
      【解决方案4】:

      我必须这样写:

      for(int i = 0; i <100; i++)
      {
         TextBox t = new TextBox(){ Id = "txt_" + i, Value = "txt_" + i};
         t.TextChanged += new System.EventHandler(this.textBox_Textchanged);
        Page.Controls.Add(t);
      
      }
      
      //and for event on TextChanged
      private void textBox_Textchanged(object sender, EventArgs e)
          {
              TextBox textBox = sender as TextBox;
      
              if (textBox != null)
              {
      ////
              }
          }
      

      【讨论】:

      • @feedwall:不,您不能在设计时拥有像 VB6 中那样的数组。但是,您可以为所有控件使用一个公共事件处理程序,但您需要在设计时或通过代码手动连接它们。
      【解决方案5】:

      另外需要注意的是:如果您真的需要在一个表单上编辑 100 个字符串,您可能应该考虑一下 100 个文本框是否真的是最好的方法。也许 ListView、DataGridView 或 PropertyGrid 会更合适。

      这几乎适用于您认为需要大量控件的任何时候。

      【讨论】:

        【解决方案6】:

        如果您使用的是 Web 窗体而不是 MVC,则可以访问页面上的一组控件,如 Using the Controls Collection in an ASP.NET Web Page 所示。本质上,控件集合是一棵树,其中包含第一级子控件的页面和一些具有自己子控件的项目。有关如何跟随树的示例,请参阅 How to: Locate the Web Forms Controls on a Page by Walking the Controls Collection

        另外,请参阅How to: Add Controls to an ASP.NET Web Page Programmatically

        只要所需的签名相同,您就可以对多个项目使用相同的事件处理程序。

        对于 Windows 窗体,这几乎相同,因为它们基于相似的架构模型,但您需要 Control.Controls PropertyHow to: Add Controls to Windows Forms

        【讨论】:

        • 就基本架构而言,Windows 窗体和 Web 窗体模型几乎相同。大部分技术都适用。我在答案中添加了更多内容。
        【解决方案7】:

        保持简单:

        TextBox[] keybox = new TextBox[16];   //create an array
        
        for (int i=0; i<16; i++) 
        {
            keybox[i] = new TextBox();        //initialize (create storage for elements)
            keybox[i].Tag = i;                //Tag prop = index (not available at design time)
            keybox[i].KeyDown += keybox_down; //define event handler for array
        }
        
        private void keybox_down(object sender, KeyEventArgs e)
        {
            int index = (int)((TextBox)sender).Tag    //get index of element that fired event
            ...
        }
        

        【讨论】:

          猜你喜欢
          • 2011-02-24
          • 2012-09-04
          • 2015-07-19
          • 2021-12-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-02
          相关资源
          最近更新 更多