I'm developing a booking system. I'm using multiple DGVs to visually display booked slots for different rooms based on 30 minute slot cells in a DGV, each room has its own DGV. I used a foreach statement on each room to create a new DGV, change the properties appropriately, add rows for each time slot and if they match a booking time, change the cell color and value before adding it to the DGV and adding the DGV to the form.
The code for this is:
public partial class BookingSystem : Form
{
List<string> RoomList = new List<string>();
public BookingSystem()
{
InitializeComponent();
this.Text = "Booking System - " DateTime.Today.DayOfWeek.ToString() " " DateTime.Today.ToString("dd MMM yyyy");
RoomList.Add("Community Room 3");
RoomList.Add("Community Room 2");
RoomList.Add("Community Room 1");
RoomList.Add("Sports Hall");
//RoomList.Add("New Room");
DateTime bookingStart = DateTime.Parse("23/11/2021 10:30:00");
DateTime bookingStart2 = DateTime.Parse("23/11/2021 11:00:00");
DateTime bookingEnd = DateTime.Parse("23/11/2021 11:30:00");
this.Width = 1080;
foreach (string room in RoomList)
{
DataGridViewCellStyle dgvCellStyle = new DataGridViewCellStyle();
Color color = Color.FromArgb(255, 224, 224, 224);
dgvCellStyle.BackColor = color;
DataGridView roomSchedule = new DataGridView();
roomSchedule.Dock = DockStyle.Left;
roomSchedule.Width = 200;
roomSchedule.Columns.Add(room, room);
roomSchedule.Columns[0].Width = 135;
roomSchedule.RowHeadersWidth = 63;
roomSchedule.AlternatingRowsDefaultCellStyle = dgvCellStyle;
roomSchedule.RowHeadersBorderStyle = DataGridViewHeaderBorderStyle.Raised;
roomSchedule.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single;
//roomSchedule.ReadOnly = true;
roomSchedule.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect;
roomSchedule.AllowUserToResizeRows = false;
DateTime openingTime = DateTime.Parse("07:00");
DateTime closingTime = DateTime.Parse("22:00");
TimeSpan openingHours = closingTime - openingTime;
DateTime currentTimeSlot = openingTime;
double totalRows = openingHours.TotalMinutes / 30;
int rows = 0;
while (rows <= totalRows)
{
DataGridViewRow row = new DataGridViewRow();
DataGridViewCellStyle bookedCellStyle = new DataGridViewCellStyle();
bookedCellStyle.BackColor = Color.Moccasin;
DataGridViewCell bookedCell = new DataGridViewTextBoxCell();
bookedCell.Value = "Class Name";
bookedCell.Style = bookedCellStyle;
row.HeaderCell.Value = currentTimeSlot.ToString("HH:mm");
roomSchedule.Rows.Add(row);
if (currentTimeSlot.TimeOfDay == bookingStart.TimeOfDay || currentTimeSlot.TimeOfDay == bookingStart2.TimeOfDay)
{
if (room == "Sports Hall")
{
row.Cells[0] = bookedCell;
//row.Cells[0].Value = "Class Name";
}
}
currentTimeSlot = currentTimeSlot.AddMinutes(30);
roomSchedule.RowsDefaultCellStyle.SelectionBackColor = System.Drawing.Color.Transparent;
rows ;
}
dgvBox.Controls.Add(roomSchedule);
}
}
}
However when a value for a cell is entered this way, the value gets cleared when ever the cell is selected.
Disabling the DGVs or making the DGV rows read only would fix this issue but I would like to keep the ability to select cells.
The problem is being created by setting the cell value using DataGridViewCellStyle.Value
bookedCell.Value = "Gravity ASD";
but I can't find any other way to set the cell value, as using:
row.Cells[0].Value = "Class Name";
before the row is added to the DGV, gives me this exception message: Specified argument was out of the range of valid values
and if its after the row is added to the DGV it gives me this exception message: Index was out of range. Must be non-negative and less than the size of the collection
Is there a way to either add the value to the cell another way or a way to stop the selected cell value from being cleared?
CodePudding user response:
It appears you may be making this more complicated than it has to be. However; I may not understand the requirements. After some small tests, is what stands out as ODD is the way the code is adding the rows to the grid. Starting with…
DataGridViewRow row = new DataGridViewRow(); … ? …
this is odd and it may work; however, it is unnecessary and it appears to be creating some odd behavior as you describe.
I would think that since you already have the DataGridView
… roomSchedule
WITH a column, that you may want to get a “NEW ROW” from “THAT GRID” as opposed to creating a new row from scratch. Something like…
int rowIndex = roomSchedule.Rows.Add();
DataGridViewRow row = roomSchedule.Rows[rowIndex];
The same idea would apply to the “CELL” in the row. There is no need to “create” a new one since the row we got from the grid already has a cell. I hope that makes sense.
DataGridViewCell bookedCell = row.Cells[0];
These changes appear to make the grid behave as expected. Sorry if I am missing something and I hope this makes sense.