[C #] allows the DataGridView input to update the calculation columns in the data source in real time,
This article applies to Winform development, and the data source of the DataGridView dview is able/DataView.
Prerequisites:Familiar with DataTable and DataView
Please:Better Solution
Consider the following scenario:
Column B of A DataTable (dt) is A computing column (the Expression attribute is set) and is calculated based on the data of column, the dt is bound to A DataGridView (dgv). columns A and B must be displayed in dgv. Column A can be edited (ReadOnly = false ). When you edit column A (input or delete), column B can change in real time. For example:
The [target file name] is calculated based on the [model number] and [color number] (connection string). When editing the model number/color number, the target file name can change in real time.
Yuanyou, who is familiar with dgv, knows that the above effect cannot be achieved without special handling. The reason is that dgv submits changes to the data source only when the focus leaves the edit cell (CurrentCell) by default, and if the focus is still in the same row (that is, CurrentCell changes, but CurrentRow is not changed,Source line of the rowIt is still in the editing status (DataRowView. IsEdit is true), and the calculation column is not updated. The calculation column is updated only when the focus is removed from this row (to another row or other controls. -- The amount of information in this section is a little large. yuanyou, who are not familiar with the dgv commit mechanism, may need to use the following further instructions to understand it ~ Please bypass the old bird. First, let's get to know several concepts:
- Dgv cell: maid
- Dgv row: DataGridViewRow
- The source row of the dgv row: DataRowView. When a dgv is bound to a data source, each row corresponds to a row (or an item) in the data source. This is what I call the source row ]. You can use DataGridViewRow. obtain the DataBoundItem attribute. The attribute type is object. When the data source of dgv is able or DataView (dv), the actual type of DataBoundItem is DataRowView, which can be understood as the row of DataView. Dv is based on dt, so dv corresponds to another dt, so DataRowView also corresponds to a DataRow, which can be obtained through DataRowView. Row. A simple expression is: DataGridViewRow (accessing the DataBoundItem attribute) → DataRowView (accessing the Row attribute) → DataRow
- Dgv has the concept of cells and the object class (DataGridViewCell), but dt and dv do not. The latter is only at the row level, although the value of a cell can be accessed through DataRow [x] Or DataRowView [x], there is no entity class indicating a cell like DataCell at the class level, that is, operations such as dt and dv editing/submission are in the unit of [rows ].
Below is the general submission process of dgv:
① Edit dgv cell → ② finish editing (leave focus) → ③ submit the data source (the source row is still editable) → ④ focus left dgv row → ⑤ source row end editing status → ⑥ source row updates computing column (in fact, the complete process also includes other steps, such as cell data verification, but here we only talk about the links directly related to the submission ).
We can see that the key to updating calculated columns is:
Follow the regular submission process,The focus must be removed from the row where the cell is located.The goal can be achieved only when the cell is left. However, we need to update the data in real time during the editing process. Do not leave the row and do not even want to leave the cell.
I. Solve the Problem of updating computing columns in real time
It can be achieved through the CurrentCellDirtyStateChanged event of dgv:
Private void dgv_CurrentCellDirtyStateChanged (object sender, EventArgs e) {// you can determine whether the current cell has uncommitted changes. This operation can only be performed if the current cell exists. // This judgment is necessary because the following dgv. commitEdit will also trigger this event, but IsCurrentCellDirty is already false. // if no judgment is made, it will repeat and cause unnecessary consumption if (dgv. isCurrentCellDirty) {// submit the cell value to the data source, dgv. endEdit () can also be submitted, but it will end the cell editing status // while dgv. commitEdit () will remain in the editing status // The parameter is the cause of the event provided to DataError and so on dgv. commitEdit (maid. commit); // manually end the editing status of the source line. Only in this way will the computed columns of the source row be updated (dgv. currentRow. dataBoundItem as DataRowView ). endEdit (); // or EndEdit () that executes DataRow can achieve the same purpose. // (dgv. currentRow. dataBoundItem as DataRowView ). row. endEdit ();}}
This event is used to update the dgv cell value to the data source, and the source row editing status. As we can say, this is a problem. In fact, it can also reflect the input of computing columns in real time, but there is another problem at the user experience level, that is, the Cell will select all the content after each input,
That is, if continuous input is required, you must use the mouse or arrow key after each input to cancel all selection and position the cursor to the correct position ~ This is not a pain point, it must be solved! The reason why all the selections are selected is unknown,I guessThis is because updates to the data source affect dgv in turn. I tried CellEnter, CellBeginEdit, EditingControlShowing, dgv. EditingControl, and other things, which were not ideal. It was not useless at all, but the input focus was incorrect. In short, I had a hard time, and finally made a different solution.
Ii. fixed the problem of automatic selection after typing
I came up with the idea of the control message. The cell of dgv actually carries an editing control (such as TextBox and CheckBox), so the Administrator determines Why it is all selected, in the end, it is always necessary to select all the received messages. Then I use spy ++ to intercept the messages, and I found that:
In a rough view, it is EM_SETSEL. After learning it, It is EM_SETSEL, so the next thing to do is to customize a text editing control so that it can ignore this message, make the control a text edit control in the dgv cell. To learn more, there are the following routines:
In this example, you can solve the problem of Selecting All dgv cells after completing the preceding steps. For a complete set of custom cell controls, refer to MSDN.
Should ape friends requirements, put demo: http://pan.baidu.com/s/1ntDXz9f
-Wen Bi-