CurrentCellDirtyStateChanged 事件代碼將復選框的數量限制為 (2)。帶有復選框的行包含可編輯的資料,用于計算剩余未選中的只讀行中的值。我希望資料網格通過更改選中行的顏色來指示可編輯的行,并將剩余的行設為只讀。CurrentCellDirtyStateChanged 事件用于管理復選框,但與用于更改行顏色的 CellClick 事件沖突。這些框不會一致地檢查和更改顏色。任何幫助將不勝感激。
using System.Linq;
private void dgvParameters_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (dgvParameters.CurrentCell is DataGridViewCheckBoxCell && dgvParameters.IsCurrentCellDirty && !(bool)dgvParameters.CurrentCell.FormattedValue)
{
var count = dgvParameters.Rows.Cast<DataGridViewRow>()
.SelectMany(r => r.Cells.OfType<DataGridViewCheckBoxCell>()
.Where(c => (bool)c.FormattedValue))
.Count();
if (count == 2) dgvParameters.CancelEdit();
}
}
private void dgvParameters_CellClick(object sender, DataGridViewCellEventArgs e)
{
int index = dgvParameters.CurrentRow.Index;
DataGridViewCellStyle CheckedStyle;
DataGridViewCellStyle UnCheckedStyle;
CheckedStyle = new DataGridViewCellStyle();
UnCheckedStyle = new DataGridViewCellStyle();
CheckedStyle.BackColor = Color.White;
CheckedStyle.ForeColor = Color.Black;
UnCheckedStyle.BackColor = Color.LightGray;
UnCheckedStyle.ForeColor = Color.Black;
bool isSelect = dgvParameters[5, index].Value as bool? ?? false;
if (Convert.ToBoolean(row.Cells[5].Value))
{
dgvParameters.Rows[index].Cells[1].Style = CheckedStyle;
dgvParameters.Rows[index].Cells[3].Style = CheckedStyle;
dgvParameters.Rows[index].Cells[1].ReadOnly = false;
dgvParameters.Rows[index].Cells[3].ReadOnly = false;
}
else
{
dgvParameters.Rows[index].Cells[1].Style = UnCheckedStyle;
dgvParameters.Rows[index].Cells[3].Style = UnCheckedStyle;
dgvParameters.Rows[index].Cells[1].ReadOnly = true;
dgvParameters.Rows[index].Cells[3].ReadOnly = true;
}
}
uj5u.com熱心網友回復:
您可以繼續使用該CurrentCellDirtyStateChanged方法并處理CellValueChanged事件以根據DataGridViewCheckBoxCell.
首先,確保您通過設計器或代碼設定目標單元格的默認值。我假設復選框單元格的初始值為false.
public YourForm()
{
InitializeComponent();
foreach (int i in new[] { 1, 3 })
{
dgvParameters.Columns[i].DefaultCellStyle.BackColor = Color.LightGray;
dgvParameters.Columns[i].DefaultCellStyle.ForeColor = Color.Gray;
dgvParameters.Columns[i].ReadOnly = true;
}
}
其次,修改CurrentCellDirtyStateChanged事件如下...
private void dgvParameters_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (dgvParameters.CurrentCell is DataGridViewCheckBoxCell &&
dgvParameters.IsCurrentCellDirty)
{
if (!(bool)dgvParameters.CurrentCell.FormattedValue)
{
var count = dgvParameters.Rows.Cast<DataGridViewRow>()
.SelectMany(r => r.Cells.OfType<DataGridViewCheckBoxCell>()
.Where(c => (bool)c.FormattedValue))
.Count();
if (count == 2) dgvParameters.CancelEdit();
}
dgvParameters.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
請注意,dgvParameters.CommitEdit(DataGridViewDataErrorContexts.Commit);當您切換值時,該行可以應用并查看結果。如果您需要保持當前行的臟狀態并在單元格離開時提交更改,請對其進行注釋。
最后,如果是復選框單元格的索引,則處理CellValueChanged事件以更新目標單元格...e.ColumnIndex
private void dgvParameters_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && e.ColumnIndex == 5)
{
var cell5 = dgvParameters.Rows[e.RowIndex].Cells[e.ColumnIndex];
bool isReadOnly = !(bool)cell5.FormattedValue;
Color backColor, foreColor;
if (isReadOnly)
{
backColor = Color.LightGray;
foreColor = Color.Gray;
}
else
{
backColor = Color.White;
foreColor = Color.Black;
}
foreach (int i in new[] { 1, 3 })
{
dgvParameters.Rows[e.RowIndex].Cells[i].Style.BackColor = backColor;
dgvParameters.Rows[e.RowIndex].Cells[i].Style.ForeColor = foreColor;
dgvParameters.Rows[e.RowIndex].Cells[i].ReadOnly = isReadOnly;
}
}
}
這樣,您只需處理一行,而無需考慮其余部分。
uj5u.com熱心網友回復:
您的問題說您希望未選中的行應該是只讀的。一個明顯的沖突是,如果一行真正完全是只讀的,那么就沒有辦法檢查它以使其可編輯。我的第一個建議是制定一種refreshStyles考慮哪些單元格的方法,DataGridViewCheckBoxCell以便無論行的狀態如何,都可以始終切換這些單元格。
private void refreshStyles()
{
for (int i = 0; i < DataSource.Count; i )
{
var item = DataSource[i];
var row = dataGridView.Rows[i];
// Use System.Linq to get all of the row cells that aren't checkboxes.
var cells =
row.Cells.Cast<DataGridViewCell>()
.Where(_ => !(_ is DataGridViewCheckBoxCell));
if(item.IsChecked)
{
row.DefaultCellStyle.BackColor = Color.Azure;
foreach (var cell in cells) cell.ReadOnly = false;
}
else
{
dataGridView.Rows[i].DefaultCellStyle.BackColor =
Color.FromArgb(0xf0, 0xf0, 0xf0);
foreach (var cell in cells) cell.ReadOnly = true;
}
}
}
這是使 DGV 呈現混合只讀行和可編輯行的一步。

這一切都基于DataSource將 DGV 的屬性設定為我們將呼叫的類的系結串列DgvItem的實作如圖所示。制作IsChecked系結屬性的原因是為了讓 DataSource 在其值更改時發送通知(否則它僅在添加或洗掉專案時通知)。
class DgvItem : INotifyPropertyChanged
{
bool _IsChecked = false;
public bool IsChecked
{
get => _IsChecked;
set
{
if (!Equals(_IsChecked, value))
{
_IsChecked = value;
OnPropertyChanged();
}
}
}
public string Description { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(
[CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
初始化
override唯一剩下的就是把它們粘在一起Load事件中將它們粘合在一起MainForm。
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
dataGridView.AllowUserToAddRows = false;
// Set the DataSource of DGV to a binding list of 'DgvItem' instances.
dataGridView.DataSource = DataSource;
for (int i = 1; i <= 5; i )
{
DataSource.Add(new DgvItem { Description = $"Item {i}" });
}
// Do a little column formatting
dataGridView.Columns[nameof(DgvItem.IsChecked)].Width = 50;
dataGridView.Columns[nameof(DgvItem.IsChecked)].HeaderText = string.Empty;
dataGridView.Columns[nameof(DgvItem.Description)].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
// Ensure the row isn't stuck in edit mode when a checkbox changes
dataGridView.CurrentCellDirtyStateChanged = (sender, e) =>
{
if(dataGridView.CurrentCell is DataGridViewCheckBoxCell)
{
dataGridView.EndEdit();
}
};
// Get notified when a checkbox changes
DataSource.ListChanged = (sender, e) =>
{
switch (e.ListChangedType)
{
case ListChangedType.ItemChanged:
// Make changes to row styles when that happens.
refreshStyles();
break;
}
};
// Init the styles
refreshStyles();
}
我希望這能給你一些想法來實作你想要的結果。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/506404.html
上一篇:是什么導致了僵局?
