【问题标题】:How can I simplify this code with a for loop to update many controls?如何使用 for 循环简化此代码以更新许多控件?
【发布时间】:2020-10-18 03:37:46
【问题描述】:

我已经完成了以下代码并且运行良好。我想知道如何做一个 for 循环来将这段代码从 38 行清理为 2 行。

        s0s.Text = seg[0].start.ToString("X8");
        s0e.Text = seg[0].end.ToString("X8");
        s1s.Text = seg[1].start.ToString("X8");
        s1e.Text = seg[1].end.ToString("X8");
        // .. many more ..
        s19s.Text = seg[19].start.ToString("X8");
        s19e.Text = seg[19].end.ToString("X8");

我显然可以进行 seg[i] 替换,但我该如何处理文本框呢?

【问题讨论】:

  • 你能解释一下seg是什么类型吗?
  • seg 是我存储段信息的数组。如此处所定义。字节[] 箱;段[]段;
  • 不清楚segment 对象是什么。你能展示它的结构吗?我只是对 .start.end 属性感到困惑,这些属性在我的测试中不存在。

标签: c# loops for-loop textbox


【解决方案1】:

我想您可以使用Controls 属性并调用OfType<T>() 来获取FormTextBoxes 的所有实例实例

根据指定类型过滤 IEnumerable 的元素。

然后根据控件Name将结果转换为Dictionary

// this could potentially be done in the constructor
var dict = Controls.OfType<TextBox>().ToDictionary(x => x.Name);

for (int i = 0; i < 19; i++)
{
    dict[$"s{i}s"].Text = $"{seg[i].Start:X8}";
    dict[$"s{i}e"].Text = $"{seg[i].End:X8}";
}

注意:此代码未经测试,仅作为可能解决方案的指南

【讨论】:

  • 如果dict 中的一个键与字符串“sXs”或“sXe”之一不匹配,代码不会崩溃吗?该代码正在抓取所有文本框。另外,如果文本框少于 19 个怎么办?我认为您至少必须将这些文本框与某个容器组合在一起。
  • @JohnG 是的,假设是文本框存在。你是对的,它会抓取所有的文本框,如果它们是某个控件的父级(在更复杂的表单上)可能会更好。
  • 我同意,但我仍然不确定seg 是什么?我不确定.start.end 是什么意思。 seg 不是字符串数组或列表。
  • seg 只是段及其名称的缩写。
【解决方案2】:

我很想这样做。首先创建两个控件列表,开始和结束:

var starts = new List<TextBox>
{
    s0s,
    s1s,
    //...
    s19s
};
var ends = new List<TextBox>
{
    s0e,
    s1e,
    //...
    s19e
};

然后遍历每个列表:

var i = 0;
foreach (var start in starts)
{
    start.Text = seg[i].start.ToString("X8");
    ++i;
}
i = 0;
foreach (var end in ends)
{
    start.Text = seg[i].end.ToString("X8");
    ++i;
}

不过,您的索引和控制编号需要完美对齐。

注意:与 TheGeneral 的代码一样,这是未经测试的(我们都不想创建一个包含 38 个具有特定名称的文本框的表单)

【讨论】:

  • 如果我必须这样做,那么它与我现在所拥有的并没有太大的不同。我可能会在代码中添加更多字母,但仅此而已。我仍然必须一一定义它。我正在寻找一种可以将变量添加到名称中间字母的方法,以便我可以通过循环引用它。
  • @highlander:不同之处在于,在我的例子中,您首先声明要操作哪些对象,然后描述您将要执行的操作。如果您的规格发生变化,并且您需要对这些控件执行不同的操作,那么您需要做的就是更改其中一个或两个短循环。在您的原始代码中,您需要仔细更改 38 行密集代码。编写代码时应该始终考虑可维护性
【解决方案3】:

根据文本框名称,我建议使用旨在显示事物集合的控件的替代方法 - DataGridView 将是选项之一。

通过数据绑定,您可以实现更易于维护的代码

public class MyItem
{
    public int Start { get; set; }

    public int End { get; set; }
}

在表单中创建一个带有两个有界列的datagridview,您可以在winforms设计器中执行此操作,而无需手动编写以下代码。

// constructor
public MyForm()
{
    var startColumn = new DataGridViewTextBoxColumn();
    startColumn.DataPropertyName = "Start"; // Name of the property in MyItem class
    startColumn.DefaultCellStyle.Format = "X8";

    var endColumn = new DataGridViewTextBoxColumn();
    endColumn.DataPropertyName = "End"; // Name of the property in MyItem class
    endColumn.DefaultCellStyle.Format = "X8";

    myDataGridView.Columns.AddRange(startColumn, endColumn);
    myDataGridView.AutoGenerateColumns = false; 
}

private void Form1_Load(object sender, EventArgs e)
{
    var items = new List<MyItem>
    {
        new MyItem { Start = 10, End = 20 },
        new MyItem { Start = 11, End = 19 },
        new MyItem { Start = 12, End = 18 }
    };

    myDataGridView.DataSource = items;
}

【讨论】:

    【解决方案4】:

    首先,当您创建它们的变量时,将它们全部插入到一个数组中。然后运行如下循环:

    for (int i; int < 19(your list); i++)
    {
        your list[i].Text = seg[i].start.ToString("X8");
        your list[i].Text = seg[i].end.ToString("X8");
    }
    

    【讨论】:

    • 是的,但是 s 0 s.text 呢? i 必须匹配 s... 之间的数字,例如 s1s.Text = seg[1].start.ToString("X8");等等等等等等。
    猜你喜欢
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-03
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多