I'm using the "Control" cell type to hold a panel, which contains a Label and Checkbox control within it. The initial problem I had was needing to click the checkbox twice for it to trigger (once to activate the cell, the second time to trigger the checkbox), however this is resolved with the PanelEnter handler in my code.
My problem now: if I display a messagebox as part of the CheckedChanged handler, it causes the cell to turn completely white/blank while the messagebox is displayed. I don't want the cell to turn completely white, but want it to keep displaying what was already in the cell, even while the messagebox is displayed. Stepping through the code in Debug mode shows this occurs right as the Messagebox line is reached. I suspect this is something to do with the cell/panel redrawing itself, however I have been unsuccessful finding a way to prevent this.
This only occurs when going through the PanelEnter event handler; if I click elsewhere in the panel first to activate the cell, then click the checkbox, the cell displays as expected (however this requires 2 clicks to trigger the checkbox which I was trying to avoid).
I have included the following code sample which recreates the issue I am having.
---- Code Sample ----
Imports Syncfusion.Windows.Forms.Grid
Public Class Form4
Dim grid As New GridControl
Private Sub Form4_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.Controls.Add(grid)
grid.Visible = True
grid.RowCount = 2
grid.ColCount = 2
grid.SetRowHeight(1, 2, 30)
grid.SetColWidth(1, 2, 100)
grid.Width = 500
grid.Height = 500
For i As Integer = 1 To 2
Dim panel As New Panel With {
.BackColor = Color.Gray
}
Dim label As New Label With {
.Width = grid.GetColWidth(1) / 4,
.Height = grid.GetRowHeight(i) - 5,
.Top = 2,
.BackColor = Color.Yellow,
.BorderStyle = BorderStyle.Fixed3D,
.Text = "1"
}
panel.Controls.Add(label)
Dim cb As New CheckBox With {
.Appearance = Appearance.Button,
.Checked = False,
.BackColor = Color.Black,
.Text = 0,
.Width = grid.GetColWidth(1) / 4,
.Height = grid.GetRowHeight(i) - 4,
.Top = 1,
.Left = grid.GetColWidth(1) / 4 * 3 - 3
}
panel.Controls.Add(cb)
AddHandler cb.CheckedChanged, AddressOf Cb_CheckedChanged
'Sets the control object.
Me.grid(i, 1).Control = panel
Me.grid(i, 1).CellType = "Control"
AddHandler panel.Enter, AddressOf Panel_Enter
Next
End Sub
Private Sub Panel_Enter(sender As Panel, e As EventArgs) 'this function makes it so the checkbox only needs to be clicked once to acttivate, due to being in a panel contreol
Dim loc = grid.LastMousePositionToClient
Dim mp = MousePosition
Dim row As Integer, col As Integer
Dim cb As CheckBox
grid.PointToRowCol(loc, row, col)
grid.CurrentCell.SetCurrentCellNoActivate(row, col)
For Each c In sender.Controls
If c.GetType = GetType(CheckBox) Then
Dim p = sender.PointToClient(mp)
If (c.Bounds.Contains(p)) Then
c.Checked = Not c.Checked
End If
End If
Next
End Sub
Private Sub Cb_CheckedChanged(sender As CheckBox, e As EventArgs)
MsgBox("Example message causing blanked cell")
If sender.Checked Then
sender.Text = 1
sender.ForeColor = Color.Green
Else
sender.Text = 0
sender.ForeColor = Color.Red
End If
End Sub
End Class
//Event subscription
gridControl1.DrawCellDisplayText += GridControl1_DrawCellDisplayText;
//To draw the text manually.
private void GridControl1_DrawCellDisplayText(object sender, GridDrawCellDisplayTextEventArgs e)
{
if(gridControl1[e.RowIndex,e.ColIndex].CellType == GridCellTypeName.Control)
{
if(e.DisplayText != "")
{
e.Graphics.DrawString(e.DisplayText, gridControl1[e.RowIndex, e.ColIndex].Font.GdipFont, new SolidBrush(gridControl1[e.RowIndex, e.ColIndex].TextColor), e.TextRectangle);
}
}
} |
I tried the above fix with no improvement. I don't believe the problem is with display text rendering as we are not rendering text in the cell, but rather the rendering of the panel control in the control cell. Please see attached video.
Hello,
I have tried the changes you suggested, however this brings me back to the original problem I was trying to avoid with these functions. With your proposed solution it is necessary to click the checkbox twice for it to actually change - once to activate the panel and again to actually cause the checkbox to change. See attached video where the first click does not cause the checkbox to change state, but the second click does.
private void Grid_CellClick(object sender, GridCellClickEventArgs e)
{
Point loc = grid.LastMousePositionToClient();
Point mp = MousePosition;
int row = 0;
int col = 0;
grid.PointToRowCol(loc, out row, out col);
Rectangle rect = grid.RangeInfoToRectangle(GridRangeInfo.Cell(row, col));
if (row == 0)
return;
grid.CurrentCell.Activate(row, col);
foreach (Control c in (grid[row, col].Control as Panel).Controls)
{
if (c.GetType() == typeof(CheckBox))
{
Point p = ((grid[row, col].Control as Panel).PointToClient(mp));
if (c.Bounds.Contains(p))
{
(c as CheckBox).Checked = !(c as CheckBox).Checked;
}
}
}
}
private void Cb_CheckedChanged(object sender, EventArgs e)
{
Point loc = grid.LastMousePositionToClient();
Point mp = MousePosition;
int row = 0;
int col = 0;
grid.PointToRowCol(loc, out row, out col);
grid.CurrentCell.Activate(row,col);
(sender as CheckBox).Parent.Focus();
MessageBox.Show("Example message causing blanked cell");
CheckBox cbb = (sender as CheckBox);
if (cbb.Checked)
{
cbb.Text = "1";
cbb.ForeColor = Color.Green;
}
else
{
cbb.Text = "0";
cbb.ForeColor = Color.Red;
}
this.grid.CurrentCell.Refresh();
} |
This solution worked! Thanks for your assistance.
One additional modification is to add this.grid.CurrentCell.Deactivate at the end of the CheckedChanged event so the checkbox can be triggered again, if desired, without first needing to leave the cell (as the CellClick event won't trigger if the cell is still active).
Hi Mike,
Thank you for the update.
We are glad that the reported use case is resolved with provided solution. Please get back to us if you need any further assistance.
Regards,
Arulpriya Ramalingam