我正在开发一个剧院预订软件。我使用的是 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:
这是 IsException
和 ExistsReservations
方法:
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/