簡體   English   中英

如何檢測 datagridview 行中的更改?

[英]How to detect changes in a datagridview row?

我有一個 15 列的數據網格視圖。 行從中填充,我想要的是一個事件,function 或檢測行(而不是單元格)變化的方法。

我試過了:

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是一個復選框類型的列,當檢測到單元格中的更改時設置為 true,但它不能很好地工作,因為 CellValueChanged 事件僅在單元格離開編輯模式或焦點更改到另一個單元格時觸發。

我猜RowDirtyStateNeeded是您正在尋找的。 將 DataGridView 的VirtualMode屬性設置為 true 並添加RowDirtyStateNeeded處理程序。 觸發事件時,檢查QuestionEventArgs是否。 Respose是真的。

為 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();
}

根據需要修改行為。

我想要的是一個事件,function 或檢測行變化的方法

您是否希望在操作員完成對一行中的一個或多個單元格的編輯並選擇另一行進行編輯時立即收到通知? 在這種情況下,使用事件DataGridView.RowValidatingDataGridView.RowValidated

不確定這是否是一個不錯的界面。 假設在輸入客戶地址的過程中,操作員決定從他屏幕上的文本編輯器中復制粘貼它?

我認為一個好的 HMI 是讓操作員安心地完成他的任務,並且只有在操作員指示他完成對 DataGridView 的編輯時才應該開始處理編輯。

為了能夠看到所有的變化:

使用 Visual Studio Designer,您可能會添加列。 您需要指定哪個列應該顯示哪個屬性:

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);
    ...
}

您需要一個程序來獲取必須顯示的購買(在此問題的 scope 中)

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

要顯示購買並了解更改:使用 BindingList:

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

初始化數據網格視圖:

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 和選定的 DisplayedPurchase 感興趣(如果多選)

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);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM