如何正确设置DataGridViewCheckBoxCell.ReadOnly
属性并将其绘制为灰色?原始的DataGridCheckBoxCell不会这样做。
我的DataGridView
的数据来自BindingSource
。加载数据后,我将特定单元格设置为ReadOnly。
然而,实验表明它使其他单元格的ReadOnly属性不一致。许多调试会话显示 - 有时 - 同一列中的其他单元重新实例化,从而重置其ReadOnly标志。这导致绘制单元格不一致。
以下是工作示例应用程序的代码。它有4行。但是,如果在单元格的构造函数上设置断点,则会看到它实例化的次数超过4次。单击该复选框时,有时您会看到该单元格也会重新复制。这真让我困惑。
我正在运行.NET 3.5
Form1.cs的
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace DataGridPaintingIssue
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
estimateLineBindingSource.DataSource = createMockData();
this.Load += Form_Load;
}
private void Form_Load(object sender, EventArgs eventArgs)
{
setReadOnly();
}
private List<EstimateLineNet> createMockData()
{
var result = new List<EstimateLineNet>()
{
new EstimateLineNet("*", false, "HEADER"),
new EstimateLineNet(null, false, "Child"),
new EstimateLineNet(null, true, "openitem"),
new EstimateLineNet(null, false, "Child3"),
};
return result;
}
private void setReadOnly()
{
estimateGridView.Rows[1].Cells[2].ReadOnly = true; //manually set a specific cell's ReadOnly flag.
}
}
public class OpenItemCheckBoxColumn : DataGridViewCheckBoxColumn
{
public OpenItemCheckBoxColumn()
{
init();
}
private void init()
{
CellTemplate = new OpenItemCheckBoxCell();
}
public class OpenItemCheckBoxCell : DataGridViewCheckBoxCell
{
public OpenItemCheckBoxCell()
{
;//breakpoint shows sometimes the cell reinstantiates.
}
private DataGridViewElementStates _lastState;
private bool _lastReadOnly;
protected override void Paint(
Graphics graphics,
Rectangle clipBounds,
Rectangle cellBounds,
int rowIndex,
DataGridViewElementStates elementState,
object value,
object formattedValue,
string errorText,
DataGridViewCellStyle cellStyle,
DataGridViewAdvancedBorderStyle advancedBorderStyle,
DataGridViewPaintParts paintParts)
{
//breakpoint with condition _lastState != elementState shows the ReadOnly flag resets to false
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText,
cellStyle, advancedBorderStyle, paintParts);
_lastState = elementState;
_lastReadOnly = ReadOnly; //need to persist this ReadOnly flag.
}
}
}
public class EstimateLineNet
{
public EstimateLineNet(string asterisk, bool openItem, string description)
{
Asterisk = asterisk;
OpenItem = openItem;
Description = description;
}
public string Asterisk { get; set; }
public bool OpenItem { get; set; }
public string Description { get; set; }
}
}
Form1.Designer.cs
namespace DataGridPaintingIssue
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.estimateGridView = new System.Windows.Forms.DataGridView();
this.Asterisk = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.OpenItem = new DataGridPaintingIssue.OpenItemCheckBoxColumn();
this.Desc = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.estimateLineBindingSource = new System.Windows.Forms.BindingSource(this.components);
((System.ComponentModel.ISupportInitialize)(this.estimateGridView)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.estimateLineBindingSource)).BeginInit();
this.SuspendLayout();
//
// estimateGridView
//
this.estimateGridView.AllowUserToAddRows = false;
this.estimateGridView.AllowUserToDeleteRows = false;
this.estimateGridView.AllowUserToResizeRows = false;
this.estimateGridView.AutoGenerateColumns = false;
this.estimateGridView.ColumnHeadersHeight = 19;
this.estimateGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
this.estimateGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.Asterisk,
this.OpenItem,
this.Desc});
this.estimateGridView.DataSource = this.estimateLineBindingSource;
this.estimateGridView.Dock = System.Windows.Forms.DockStyle.Fill;
this.estimateGridView.Location = new System.Drawing.Point(0, 0);
this.estimateGridView.Name = "estimateGridView";
this.estimateGridView.Size = new System.Drawing.Size(284, 261);
this.estimateGridView.TabIndex = 0;
//
// Asterisk
//
this.Asterisk.DataPropertyName = "Asterisk";
this.Asterisk.HeaderText = "*";
this.Asterisk.MaxInputLength = 2;
this.Asterisk.Name = "Asterisk";
this.Asterisk.Width = 20;
//
// OpenItem
//
this.OpenItem.DataPropertyName = "OpenItem";
this.OpenItem.HeaderText = "O";
this.OpenItem.Name = "OpenItem";
this.OpenItem.Resizable = System.Windows.Forms.DataGridViewTriState.True;
this.OpenItem.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
this.OpenItem.Width = 30;
//
// Desc
//
this.Desc.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
this.Desc.DataPropertyName = "Description";
this.Desc.HeaderText = "Description";
this.Desc.MaxInputLength = 60;
this.Desc.Name = "Desc";
//
// estimateLineBindingSource
//
this.estimateLineBindingSource.DataSource = typeof(DataGridPaintingIssue.EstimateLineNet);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 261);
this.Controls.Add(this.estimateGridView);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.estimateGridView)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.estimateLineBindingSource)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.DataGridViewTextBoxColumn Asterisk;
private OpenItemCheckBoxColumn OpenItem;
private System.Windows.Forms.DataGridViewTextBoxColumn Desc;
private System.Windows.Forms.DataGridView estimateGridView;
private System.Windows.Forms.BindingSource estimateLineBindingSource;
}
}
答案 0 :(得分:0)
两个选项:
如果您只想将ReadOnly OpenItemCheckBoxCell
涂成灰色,请在Paint
方法的第一行添加以下内容:
this.Style.BackColor = this.ReadOnly ? Color.Gray : Color.White;
但如果您希望任何 ReadOnly
单元格显示为灰色,请在Form1
构造函数中添加以下事件处理程序:
estimateGridView.CellFormatting += estimateGridView_CellFormatting;
private void estimateGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
DataGridViewCell cell = estimateGridView[e.ColumnIndex, e.RowIndex];
cell.Style.BackColor = cell.ReadOnly ? Color.Gray : Color.White;
}
在以下选项2中,您会注意到所有单元格都是ReadOnly
。检查您的Form1.Designer
,您就会知道原因。删除以下行:
this.estimateGridView.ReadOnly = true;
this.Asterisk.ReadOnly = true;
this.OpenItem.ReadOnly = true;
this.Desc.ReadOnly = true;
现在您会注意到,您手动设置为ReadOnly
的单元格不是OpenItemCheckBoxCell
。进行以下更改并完成测试:
private void setReadOnly()
{
estimateGridView.Rows[1].Cells[1].ReadOnly = true;
}
旁注:如果您按照选项2,则可以完全删除自定义CheckBoxColumn
和CheckBoxCell
类。
附加说明:如果您只想绘制实际的CheckBox
背景灰色 - 而不是整个单元格背景 - 您将必须覆盖{{1}的绘制方法}。这是更多的工作,但您可以首先查看有关如何Create custom UI appearance for WinForms CheckBox的文章。在这种情况下,您不需要选项2。
答案 1 :(得分:0)
从多方面解决了这个问题几个星期之后,我发现每次刷新DataGrid绑定数据时,都会重新验证其所有CellTemplate
。因此,它以前的所有ReadOnly值都会丢失。答案是每次刷新后再次设置ReadOnly值。
如果你像我一样使用Cell属性(比如ReadOnly)进行自定义绘制,请记住在每次DataGrid数据刷新时首先设置值并再次重新绘制单元格。
DataGrid数据刷新 - &gt;用默认值绘制的单元格 - &gt;设置自定义单元格属性 - &gt;重新粉刷细胞