【问题标题】:How can I make a large grid of buttons (24x20 or similar) in vb.net using winforms?如何使用 winforms 在 vb.net 中制作大量按钮(24x20 或类似)?
【发布时间】:2012-05-07 11:38:31
【问题描述】:

我正在 vb.net (WinForms) 中创建一个座位预订系统,我需要用户能够选择他们希望使用的座位并让它改变颜色(这样他们就可以知道它被选中了)。

我开始尝试使用按钮,但是 480 个按钮严重减慢了表单的加载时间。然后我尝试了在行/列中带有按钮的数据网格视图,但无法使其正常工作。

我的问题是,我该怎么做?

是否值得尝试使用 480 图片框并更改其背景颜色?或者这只会像 480 个按钮一样减慢表单的速度?

【问题讨论】:

  • 你需要明确它是一个 WinForms 应用程序。
  • 可能是按钮的DataGrid?这也将解决绑定您的数据源后端持有有关免费/保留状态的信息,我猜。
  • 我试过了,但我不能让它很好地工作......
  • 嗨 John 尝试动态创建控件。
  • 是否可以让用户先选择一个部分?比如:A区,然后座位分配?它将防止用户受到巨大网格的攻击。它没有回答“我如何在 winforms 中呈现 24x20 网格”,但它可能会有所帮助。

标签: vb.net winforms button user-controls


【解决方案1】:

为了提高效率,您并不想仅仅创建大量这样的控件。最好制作一个自定义控件,在它自己的单个绘图表面上绘制所有座位。这是一个非常简单的例子:

Public Class SeatingPlan
    Public Class Seat
        Public Rectangle As Rectangle
        Public Selected As Boolean
        Public Id As String

        Public Sub New(ByVal seatId As String, ByVal x As Integer, ByVal y As Integer, ByVal width As Integer, ByVal height As Integer)
            Id = seatId
            Rectangle = New Rectangle(x, y, width, height)
        End Sub
    End Class


    Public ReadOnly Property Seats() As List(Of Seat)
        Get
            Return _seats
        End Get
    End Property
    Private _seats As List(Of Seat) = New List(Of Seat)()


    Public Event SelectedSeatsChanged()


    Private Sub SeatingPlan_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick
        For Each seat As Seat In _seats
            If seat.Rectangle.Contains(e.Location) Then
                seat.Selected = Not seat.Selected
                RaiseEvent SelectedSeatsChanged()
                Exit For
            End If
        Next
        Invalidate()
    End Sub


    Private Sub SeatingPlan_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        For Each seat As Seat In _seats
            Dim seatBackColor As Color = BackColor
            Dim textColor As Color = ForeColor
            If seat.Selected Then
                seatBackColor = Color.FromKnownColor(KnownColor.Highlight)
                textColor = Color.FromKnownColor(KnownColor.HighlightText)
            End If
            e.Graphics.FillRectangle(New SolidBrush(seatBackColor), seat.Rectangle)
            e.Graphics.DrawRectangle(New Pen(ForeColor), seat.Rectangle)
            Dim textSize As SizeF = e.Graphics.MeasureString(seat.Id, Me.Font, seat.Rectangle.Width)
            e.Graphics.DrawString(seat.Id, Font, New SolidBrush(textColor), seat.Rectangle.X + ((seat.Rectangle.Width - textSize.Width) / 2), seat.Rectangle.Y + ((seat.Rectangle.Height - textSize.Height) / 2))
        Next
    End Sub


    Public Function GetSelectedSeatIds() As List(Of String)
        Dim ids As List(Of String) = New List(Of String)()
        For Each seat As Seat In _seats
            If seat.Selected Then
                ids.Add(seat.Id)
            End If
        Next
        Return ids
    End Function


    Public Sub SetSelectedSeatIds(ids As List(Of String))
        For Each seat As Seat In _seats
            seat.Selected = ids.Contains(seat.Id)
        Next
        RaiseEvent SelectedSeatsChanged()
    End Sub
End Class

然后,在您的表单中,输入如下代码来创建座位的位置:

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    SeatingPlan1.Seats.Add(New SeatingPlan.Seat("1A", 3, 3, 20, 20))
    SeatingPlan1.Seats.Add(New SeatingPlan.Seat("2A", 26, 3, 20, 20))
    SeatingPlan1.Seats.Add(New SeatingPlan.Seat("1B", 3, 26, 20, 20))
    SeatingPlan1.Seats.Add(New SeatingPlan.Seat("2B", 26, 26, 20, 20))
End Sub


Private Sub SeatingPlan1_SelectedSeatsChanged() Handles SeatingPlan1.SelectedSeatsChanged
    For Each seatId As String In SeatingPlan1.GetSelectedSeatIds
        'Do something
    Next
End Sub

【讨论】:

  • 右键单击您的项目并从上下文菜单中选择添加 > 用户控件。将其命名为 SeatingPlan(或任何您喜欢的名称),然后将此代码复制并粘贴到用户控件的代码中。然后构建项目。然后转到表单的设计器,SeatingPlan 控件应显示在工具箱的顶部。
  • 感谢这位朋友,我想这可能对我有用!
  • 如何添加索引以便记录选择的座位?
  • 我要做的是为席位列表创建一个公共属性。 It should probably raise an event too when a seat is selected or de-selected so the form can be notified when it changes.此外,座位列表可能应该由表单而不是控件的 Load 事件填充。这样就可以将控件重复用于不同的座位安排。
  • 对不起,我该怎么做:/我知道如何定义一个属性,我想出了如何获取点击框的索引,但我不知道如何让它输出正确...理想情况下,我想要一个 selecteditems 属性,例如列表框...
【解决方案2】:

试试这个:

 private void Form1_Load(object sender, EventArgs e)
        {
            int index;
            Button[] b=new Button[500];
            for(int i=0;i<24;i++)
            for(int j=0;j<20;j++)
            {
                index = (20 * i) + j;
                b[index]=new Button();
                b[index].Text=index.ToString();
                b[index].Location=new Point(j*80,i*30);
                panel1.Controls.Add(b[index]);
                b[index].Click += new EventHandler(ButtonLeft_Click);    
             }

            }

        private void ButtonLeft_Click(object sender, EventArgs e)
        {
            Button b = (Button)sender;
            if (b.BackColor == Color.Black)
                b.BackColor = Color.White;
            else
                b.BackColor = Color.Black;

              //DB Commands here    
        }

【讨论】:

  • 效果很好,但我希望有 24 个宽度的方式,12 个座位后有过道,10 个座位后有过道。
  • 另外,看起来虽然行从 1 到 20,但下一行从 10 开始?
  • 如果我在一个没有 VB 标签的 C# 问题上发布 VB.NET 代码,我会得到多少反对票?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-05
  • 1970-01-01
相关资源
最近更新 更多