winforms 如何检测DataGridView行中的更改?

vqlkdk9b  于 2023-06-06  发布在  其他
关注(0)|答案(4)|浏览(222)

我有一个有15列的datagridview。行是从它填充的,我想要的是一个事件,函数或方法来检测行(而不是单元格)的变化。
我试过:

private void DGVPurchases_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    try
    {
        if (DGVPurchases.RowCount > 0)
        {
            switch (DGVPurchases.Columns[e.ColumnIndex].Name)
            {
                case "PurchaseEmisionDate":
                case "PurchaseVendorNumber":
                //others columns
                    if (!Convert.ToBoolean(DGVPurchases.Rows[e.RowIndex].Cells["PurchaseModified"].Value))
                            DGVPurchases.Rows[e.RowIndex].Cells["PurchaseModified"].Value = true;
                    break;
            }
        }
    }
    catch (Exception er)
    {
        PBLog.Save(this, er);
        Alert.Error(Error.Value, App.Purchase.Title);
    }
}

PurchaseModified是一个checkbox类型的列,当检测到单元格中的更改时,它被设置为true,但它的工作效果不太好,因为CellValueChanged事件仅在单元格离开编辑模式或焦点更改为另一个单元格时才会触发。

vkc1a9a2

vkc1a9a21#

您可以用途:DataGridView.RowValidating和DataGridView.RowValidated。例如:

private void DGVPurchases_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    cellTextBox = e.Control as TextBox;
    if (cellTextBox != null)
        cellTextBox.TextChanged += TextBox_TextChanged;
}
private void DGVPurchases_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
    rowIndex = e.RowIndex;
    originalValue = DGVPurchases[e.ColumnIndex, e.RowIndex].Value;
}
private void DGVPurchases_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    if (cellTextBox != null)
        cellTextBox.TextChanged -= TextBox_TextChanged;
}
private void TextBox_TextChanged(object sender, EventArgs e)
{
    DGVPurchases["PurchaseModified", rowIndex].Value =
        cellTextBox.Text != originalValue.ToString();
}
ijnw1ujt

ijnw1ujt2#

我想RowDirtyStateNeeded就是你要找的。将DataGridView的VirtualMode属性设置为true并添加RowDirtyStateNeeded处理程序。当事件被触发时,检查是否为QuestionEventArgsRespose是真的。

whhtz7ly

whhtz7ly3#

为事件订阅DataGridView:

DGVPurchases.EditingControlShowing += DGVPurchases_EditingControlShowing;
DGVPurchases.CellBeginEdit += DGVPurchases_CellBeginEdit;
DGVPurchases.CellEndEdit += DGVPurchases_CellEndEdit;

定义表单中的字段:

private int rowIndex;
private object originalValue;
private TextBox cellTextBox;

实现事件处理程序:

private void DGVPurchases_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    cellTextBox = e.Control as TextBox;
    if (cellTextBox != null)
        cellTextBox.TextChanged += TextBox_TextChanged;
}
private void DGVPurchases_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
    rowIndex = e.RowIndex;
    originalValue = DGVPurchases[e.ColumnIndex, e.RowIndex].Value;
}
private void DGVPurchases_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    if (cellTextBox != null)
        cellTextBox.TextChanged -= TextBox_TextChanged;
}
private void TextBox_TextChanged(object sender, EventArgs e)
{
    DGVPurchases["PurchaseModified", rowIndex].Value =
        cellTextBox.Text != originalValue.ToString();
}

按您的意愿修改行为。

q9rjltbz

q9rjltbz4#

我想要的是一个事件、函数或方法来检测行中的变化
是否希望操作员完成编辑行中的一个或多个单元格并选择要编辑的另一行时立即收到通知?在这种情况下,使用事件DataGridView.RowValidatingDataGridView.RowValidated
不确定,虽然这将是一个很好的接口。假设在输入客户地址的中途,操作员决定从屏幕上的文本编辑器中复制粘贴它?
我认为一个好的人机界面是,你让操作员在他所有的和平做他的任务,你应该开始处理编辑只有当操作员指出,他完成了编辑DataGridView。
要查看所有更改,请执行以下操作:
使用visual studio设计器,您可能已经添加了列。您需要指定哪一列应显示哪一个属性:

class DisplayedPurchase
{
    public int Id {set; set;}
    public DateTime EmisionDate {get; set;}
    public int VendorNumber {get; set;}
    ...
}

在你的构造函数中:

public MyForm() : base()
{
    InitializeComponents();

    this.columnId.DataPropertyName = nameof(DisplayedPurchase.Id);
    this.columnEmissionDate.DataPropertyName = nameof(DisplayedPurchase.EmissionDate);
    this.columnVendorNumber.DataPropertyName = nameof(DisplayedPurchase.VendorNumber);
    ...
}

您需要一个过程来获取必须显示的Purchases(超出了本问题的范围)

public IEnumerable<DisplayedPurchase> FetchPurchases(...)
{
    ...
}

要显示采购并了解更改,请执行以下操作:使用BindingList:

BindingList<DisplayedPurchase> DisplayedPurchases
{
    get => (BindingList<DisplayedPurchase>)this.dataGridView1.DataSource;
    set => this.dataGridView1.DataSource = value;
}

初始化datagrid视图:

private void InitDisplayedPurchases()
{
    this.DisplayedPurchases = new BindingList<DisplayedPurchase>(
        this.FetchPurchases(...).ToList());
}

private void OnFormLoading(object sender, ...)
{
    this.InitDisplayedPurchases();
}

现在假设您决定操作员单击Apply-Now按钮来通知必须处理已编辑的数据。

private void OnButtonApplyNow_Clicked(object sender, ...)
{
    ICollection<DisplayedPurchase> editedPurchases = this.DisplayedPurchases;
    // find out which data is changed and process them
    this.ProcessEditedPurchases(editedPurchases);
}

因为您将所有数据都放在BindingList中,所以所有添加/删除/更改的行都会自动放在this.DisplayedPurchases中。
您可能还对当前的DisplayedPurchase和选定的DisplayedPurchases(如果多选)感兴趣

DisplayedPurchase CurrentDisplayedPurchase => (DislayedPurchase)
    this.dataGridView1.CurrentRow?.DataBoundItem;

IEnumerable<DisplayedPurchase> SelectedPurchases => this.datGridView1.SelectedRows
    .Cast<DatGridViewRow>()
    .Select(row => row.DataBoundItem)
    .Cast<DisplayedPurchase>();

如果您确实希望在编辑行后立即处理行,请考虑订阅RowValidating和RowValidated事件:

public void OnRowValidated(object sender, DataGridViewCellEventArgs e)
{
    DataGridView dataGridView = (DataGridView)sender;
    DataGridViewRow row = dataGridView.Rows[e.RowIndex];
    DisplayedPurchase editedPurchase = (DisplayedPurchase)(row.DataBoundItem);
    this.ProcessEditedPurchase(editedPurchase);
}

相关问题