Как сделать большую сетку кнопок (24x20 или аналогичных) в vb.net, используя winforms?

Я делаю систему бронирования мест в vb.net (WinForms), и мне нужно, чтобы пользователь мог выбрать место, которое он хочет использовать, и изменить его цвет (чтобы он мог сказать, что он выбран).

Я начал пытаться использовать кнопки, но 480 кнопок серьезно замедлили время загрузки формы. Затем я попробовал представление таблицы данных с кнопками в строках / столбцах, но не смог заставить это работать должным образом.

У меня вопрос, как я могу это сделать?

Стоит ли пытаться использовать 480 графических блоков и менять их цвет фона? Или это просто замедляет форму так же, как 480 кнопок?

 luke201207 мая 2012 г., 14:01
Вы должны четко дать понять, что это приложение WinForms.
 John W07 мая 2012 г., 14:06
Я пробовал это, но я не мог заставить это работать хорошо ...
 Vinod07 мая 2012 г., 14:22
Привет, Джон Попробуйте, создавая элементы управления динамически.
 hometoast07 мая 2012 г., 14:24
Можно ли позволить пользователю сначала выбрать раздел? Нравится: раздел А, затем распределение мест? Это предотвратит нападение на пользователя гигантской сеткой. Он не отвечает «как я представляю сетку 24x20 в winforms», но это может помочь.
 Filburt07 мая 2012 г., 14:04
Может быть, DataGrid кнопок? Это также решит проблему привязки вашего бэкэнда источника данных, содержащего информацию о свободном / зарезервированном статусе.

Ответы на вопрос(2)

Решение Вопроса

Ради эффективности вы действительно не хотите просто создавать тонну таких элементов управления. Было бы лучше создать один пользовательский элемент управления, который рисует все места на его собственной единственной поверхности рисования. Вот очень простой пример:

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
 John W07 мая 2012 г., 14:56
Извините за мою наивность, но как бы я сделал эту работу?
 07 мая 2012 г., 14:59
Нажмите правой кнопкой мыши на своем проекте и выберите Добавить & gt; Пользовательский контроль из контекстного меню. Назовите его SeatingPlan (или как хотите), затем скопируйте и вставьте этот код в код для пользовательского элемента управления. Тогда постройте проект. Затем перейдите к конструктору для вашей формы, и элемент управления SeatingPlan должен отображаться в верхней части панели инструментов.
 John W07 мая 2012 г., 15:06
Спасибо за этого друга, я думаю, что это, вероятно, будет работать для меня!
 John W07 мая 2012 г., 15:11
Как добавить индекс, чтобы я мог записать, какие места выбраны?
 07 мая 2012 г., 15:12
То, что я хотел бы сделать, это сделать публичную собственность для списка мест. Вероятно, он также должен вызывать событие, когда место выбрано или отменено, чтобы форма могла быть уведомлена об изменениях. Кроме того, список мест должен, вероятно, заполняться формой, а не событием Load элемента управления. Таким образом, управление может быть повторно использовано для разных вариантов рассадки.

Попробуй это:

 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    
        }
 John W07 мая 2012 г., 14:22
Кроме того, кажется, что, хотя строки идут от 1 до 20, следующая строка начинается с 10?
 07 мая 2012 г., 21:00
Сколько отрицательных отзывов я получил бы, если бы разместил код VB.NET в вопросе C #, в котором не было тега VB?
 John W07 мая 2012 г., 14:31
Как бы я это исправить?
 John W07 мая 2012 г., 14:22
Это работает довольно хорошо, но я надеялся получить 24 ширины пути с проходом после 12 мест и проходом после 10 мест в длину.
 07 мая 2012 г., 14:27
Извините, это должно быть 20.

Ваш ответ на вопрос