【问题标题】:Dynamic Variable Name Use in C# for WinFormsC# 中用于 WinForms 的动态变量名称
【发布时间】:2011-03-28 10:01:21
【问题描述】:

不确定什么是最好的表达方式,但我想知道是否可以在 C# (3.5) 中完成动态变量名访问。

这是我目前正在寻找“智能”或通过循环使其更优雅的代码。

    private void frmFilter_Load(object sender, EventArgs e)
    {
        chkCategory1.Text = categories[0];
        chkCategory2.Text = categories[1];
        chkCategory3.Text = categories[2];
        chkCategory4.Text = categories[3];
        chkCategory5.Text = categories[4];
        chkCategory6.Text = categories[5];
        chkCategory7.Text = categories[6];
        chkCategory8.Text = categories[7];
        chkCategory9.Text = categories[8];
        chkCategory10.Text = categories[9];
        chkCategory11.Text = categories[10];
        chkCategory12.Text = categories[11];  


    }

有没有办法做类似 ("chkCategory" + i.ToString()).Text 的事情?

【问题讨论】:

  • 我可能完全不知道 C# 新特性的动态部分,但我认为 C# 是一种编译语言。因此,要完成此操作,您必须创建编译器实例,生成代码,然后在拥有控件的线程的上下文中执行代码。它不实用。
  • 回答回答的一般问题:使用 WinForms 设计器时,处理复选框数组的最佳方法是什么?
  • 反射是为了什么而发明的(在您的特殊情况下,您还可以通过它们的名称访问控件)。
  • @Awaken:您可以使用 System.Windows.Forms.CheckedListBox 控件,就像我在回答中所说的那样。只需将控件拖到您的设计器上。如果您已经知道这些项目,请使用 Items 属性设置它们。否则,您可以设置 DataSource 属性,也许在调用 InitializeComponents() 之后在表单的构造函数中

标签: c# .net winforms controls


【解决方案1】:

你不需要动态的。将 chkCategory1 - 12 放入一个数组中,并使用 for 循环遍历它。我建议您将其保留在一个字段中并在表单构建时对其进行初始化,因为 chkCategory 似乎是相关的。但是如果你想要一个简单的例子来说明如何用那个简单的方法做到这一点,那么它会是这样的:

private void frmFilter_Load(object sender, EventArgs e)
{
    var chkCategories = new [] { chkCategory1, chkCategory2, chkCategory3, .......... };
    for(int i = 0 ; i < chkCategories.Length ; i++ ) 
        chkCategoies[i].Text = categories[i];
}

您对应用程序了解得更多,因此您也许可以避免写出所有控件名称 - 例如,如果它们被放置在一个公共父控件上,那么您可以通过它的子控件找到它们。

【讨论】:

  • 我不认为 OP 意味着 dynamic 动态。
  • 如何与 WinForms 设计器一起工作?我需要在代码中手动定义所有位置和属性吗?
【解决方案2】:

不,但你可以这样做(未经测试,注意语法错误):

private readonly CheckBox[] allMyCheckboxes = new CheckBox[] { chkCategory1, chkCategory2, ... }

那你只需要做

for (i = 0; i < 12; i++) allMyCheckboxes[i].Text = categories[i];

【讨论】:

    【解决方案3】:

    是的,你可以使用

      Control c = this.Controls.Find("chkCategory" + i.ToString(), true).Single();
      (c as textBox).Text = ...;
    

    添加一些错误检查并将其包装在一个不错的(扩展)方法中。


    编辑:它返回Control[],所以最后需要[0].Single()。已添加。

    【讨论】:

    • 不错!我在问题上留下的评论中得到了纠正。
    • @faux trot,这是一个库功能,而不是语言。它实际上不是我们要搜索的标识符,而是 Name 属性。不过,两者保持同步。
    • 谢谢。这是一种我不熟悉的技术,但我有几种情况会很好。
    【解决方案4】:
    for(...)
    {
         CheckBox c = this.Controls["chkCategory" + i.ToString()] as CheckBox ;
    
         c.Text = categories[i];  
    }
    

    【讨论】:

    • 完美。像魅力一样工作。
    【解决方案5】:

    您可以通过反射来做到这一点。但是不要。

    更合适的做法是实例化一个控制列表,以编程方式将它们添加到您的表单中,然后为其编制索引。

    【讨论】:

      【解决方案6】:

      有时将控件放入数组或集合中会有所帮助:

      Checkbox[] chkCataegories = new Checkbox[] { chkCategory1, chkCategory2 ... };
      for(int i = 0; i < chkCategories.Length; i++)
          chkCategories[i].Text = categories[i];
      

      作为另一种方法,您可以在运行时而不是设计时动态创建复选框:

      for(int i = 0; i < categories.Length; i++)
      {
          Checkbox chkCategory = new chkCategory { Text = categories[i] };
          someContainer.Controls.Add(chkCategory);
      }
      

      至少对于动态创建的控件,您无需在添加新类别时修改 GUI 或表单代码。

      【讨论】:

      • 有没有使用 VS 中的 WinForms 设计器的好方法?还是我必须放弃设计器并在 Load 中使用代码动态构建表单?
      【解决方案7】:

      "this.Controls["chkCategory" + i.ToString()]" 和 "this.Controls.Find("chkCategory" + i.ToString(), true)" 都不起作用...前者通知您 [] 的内容不是 int 并且后者 ControlCollection 不包含 Find 的定义。

      使用“控制 myControl1 = FindControl("TextBox2");"而是。

      我需要这个表单,因为我正在循环另一个数组,提取值并使用它们来填充表单字段。更容易查找 label1、label2、label3 等。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-22
        • 2012-10-28
        • 2022-11-24
        • 1970-01-01
        • 2014-09-17
        • 1970-01-01
        • 1970-01-01
        • 2011-07-14
        相关资源
        最近更新 更多