c# - 如何在 Windows 窗体中实例化大量按钮?

标签 c# .net windows winforms

我正在开发一个剧院预订软件。我使用的是 Windows 窗体,座位由二维数组表示。我按如下方式绘制按钮:

public void DrawSeats()
{
    // pnl_seats is a Panel
    pnl_seats.Controls.Clear();
    // Here I store all Buttons instance, to later add all buttons in one call (AddRange) to the Panel
    var btns = new List<Control>();
    // Suspend layout to avoid undesired Redraw/Refresh
    this.SuspendLayout();
    for (int y = 0; y < _seatZone.VerticalSize; y++)
    {
        for (int x = 0; x < _seatZone.HorizontalSize; x++)
        {
            // Check if this seat exists
            if (IsException(x, y))
                continue;
            // Construct the button with desired properties. SeatSize is a common value for every button
            var btn = new Button
            {
                Width = SeatSize, 
                Height = SeatSize,
                Left = (x * SeatSize),
                Top = (y * SeatSize),
                Text = y + "" + x,
                Tag = y + ";" + x, // When the button clicks, the purpose of this is to remember which seat this button is.
                Font = new Font(new FontFamily("Microsoft Sans Serif"), 6.5f)
            };

            // Check if it is already reserved
            if (ExistsReservation(x, y))
                btn.Enabled = false;
            else
                btn.Click += btn_seat_Click; // Add click event

            btns.Add(btn);
        }
    }
    // As said before, add all buttons in one call
    pnl_seats.Controls.AddRange(btns.ToArray());
    // Resume the layout
    this.ResumeLayout();
}

但是已经有一个 20 x 20 的座位区(400 个按钮),它花了将近 1 分钟来绘制它,在调试中我检查了缺乏性能,是按钮的实例化。

有没有办法让它更快?也许在安装过程中禁用所有事件或另一个具有 Click 事件的轻量级控件?

更新: lbl 是一个测试,正确的是btn,抱歉。

更新 2:

这是 IsExceptionExistsReservations 方法:

private bool IsException(int x, int y)
{
    for (var k = 0; k < _seatsExceptions.GetLength(0); k++)
        if (_seatsExceptions[k, 0] == x && _seatsExceptions[k, 1] == y)
            return true;
    return false;
}

private bool ExistsReservation(int x, int y)
{
    for (var k = 0; k < _seatsReservations.GetLength(0); k++)
        if (_seatsReservations[k, 0] == x && _seatsReservations[k, 1] == y)
            return true;
    return false;
}

最佳答案

假设您将预订和排除的数组更改为

public List<string> _seatsExceptions = new List<string>();
public List<string> _seatsReservations = new List<string>();

您在列表中添加您的排除项和保留项,例如

_seatsExceptions.Add("1;10");
_seatsExceptions.Add("4;19");
_seatsReservations.Add("2;5");
_seatsReservations.Add("5;5");

您的排除项和保留项支票可以更改为

bool IsException(int x, int y)
{
    string key = x.ToString() + ";" + y.ToString();
    return _seatsExceptions.Contains(key);
}
bool ExistsReservation(int x, int y)
{
    string key = x.ToString() + ";" + y.ToString();
    return _seatsReservations.Contains(key);
}

当然我不知道你能不能在你的程序中做这个改变。然而,迟早要考虑更改对阵列的搜索。

编辑 我进行了一些测试,虽然 20x20 按钮的虚拟网格运行良好(平均 31 毫秒 0.775 毫秒),但更大的按钮明显变慢。在 200x50 时,时间跳到 10 秒(平均 1,0675)。因此,也许需要一种不同的方法。绑定(bind)的 DataGridView 可能是更简单的解决方案,并且相对容易处理。

关于c# - 如何在 Windows 窗体中实例化大量按钮?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25058948/

相关文章:

javascript - SignalR 无法到达 JS 客户端功能

c# - ASP.NET -> 同步调用 JavaScript 函数

windows - 如何在 Windows 中使用键盘专注于桌面?

C#/林克 : Where X is Y?

.net - VB.NET : "Statement lambdas cannot be converted to expression trees" compile time error

c# - 如何将 DataTable 转换为类对象?

c# - 为什么 Thread.Sleep 在其他应用程序运行时等待的时间比请求的时间长?

windows - Windows 资源管理器使用的排序顺序中的第一个字符是什么?

python - windows下如何降级 'pip'的安装版本?

c# - NHibernate MySQL 映射设置列类型