12

In my application I am using DataGridView to display the list. When user select a record in the datagridview, it should display details in the other panel. For selection I was asked to use DataGridView1_SelectionChanged event.

The DataGridView should contain only one column, but the details display may have more information of the selected record( We can get the all the details form the database by querying with the selected Primary key value).

Please tell Is it possible to get datakey(Primary key) of the selected DataGridView record. Does DataGridView will bind based on Primary key ?

Edit

I have implemented DataGridView1.Columns["ID"].Visible = false. It worked well. For selection I added DataGridView1_SelectionChanged event.

But DataGridView1_SelectionChanged event is firing multiple times.

Sanjeev4evr
  • 403
  • 2
  • 11
  • 23
  • 1
    I would like to suggest you to add another column for primary key field and retrieve it by dgv.CurrentRow.Cells["colPKField"].Value. – Shell Apr 10 '14 at 05:18
  • But I was asked not to show the primary key in the GridView. I think it is not safe as well.. ! What do you say ? – Sanjeev4evr Apr 10 '14 at 05:39
  • 2
    you can hide that column by assigning visible property to false. `dgv.Columns["colPKField"].Visible =false;` – Shell Apr 10 '14 at 05:41
  • @Nimesh Yes, I implemented it, It worked well. But when I call dgv_SelectionChanged event, Here I ran on to serious problem, it is getting fired multiple times. I found some other also in SOF got the exception but did not explained how he resolved it. – Sanjeev4evr Apr 10 '14 at 06:21
  • try `RowEnter` event. – Shell Apr 10 '14 at 06:26
  • @Nimesh same happening with RowEnter event as well ! – Sanjeev4evr Apr 10 '14 at 06:36

4 Answers4

38

You can use DataGrid.focused property in selectionchanged event before executing the code like this :

private void dg_SelectionChanged(object sender, EventArgs e)
    {
        if (dg.Focused)
        {
            // your code
        }
    } 
Philipp
  • 4,645
  • 3
  • 47
  • 80
Mustafa Yasser
  • 381
  • 3
  • 3
  • 8
    Massive respect! This problem is a common one in Win Forms and you have the simplest solution! can you please explain what this property does ? MSDN documentation is not clear enough. – 3bdalla Jun 18 '17 at 10:24
  • Thank you so much, you save my life ;-) – Esi Jul 25 '17 at 14:44
  • Great Solution to one of those unbeatable winforms frustrations. – CJ K Jul 02 '20 at 10:10
2

I got the same problems today, after hours of experiment with it, I found a solution or rather a workaround for this problem

this.dgvSearchResult.SelectionChanged -= dgvSearchResult_SelectionChanged;
this.onSearch();
this.dgvSearchResult.SelectionChanged += new EventHandler(dgvSearchResult_SelectionChanged);

Hope it's help

Hưng
  • 21
  • 2
1

I have tried with RowEnter event but, it works fine for me. How do you check it? using message box or placing break point in the event. Because, breakpoint and messagebox will loos the focus from the selected row. Then, when you continue after messagebox or breakpoint the grid will get focused back and the event will be executed again.

Try following step to check event execution. enter image description here

To handle multiple execution.

int LastRowIndex =-1;

private void dgv_RowEnter(...)
{
    if (LastRowIndex != e.RowIndex)
    {
        //Place your code here.
    }
    LastRowIndex = e.RowIndex;
}
Shell
  • 6,818
  • 11
  • 39
  • 70
  • I tried `RowEnter` as well. But it is firing multiple times. when form loads and even it got fired when I click out side(Empty area) of the grid, So that selected row index value is 0. – Sanjeev4evr Apr 10 '14 at 09:39
  • then you can avoid multiple execution by storing last selected row index in any variable. – Shell Apr 10 '14 at 09:54
1

If the data binding is reset, you can get one SelectionChanged notifying that the list is temporarily empty followed by another after the data has populated. Worse, the selected item may not even have changed since before the reset. I verified this by checking SelectedCells on each call.

One solution is to use an invalidation variable, and check in the Application.Idle event. This has the nice effect of grouping changes and avoiding unnecessary updates. Application.Idle runs as soon as the message pump is empty, so the user won't notice a delay. It's even better if you check if a change is even required after the grid has sorted itself out.

You'll need to set up the static form instance property in the constructor.

private bool isViewUpToDate = false;

private void DataGrid_SelectionChanged(object sender, EventArgs e) => isViewUpToDate = false;

public void CheckDataGridSelectionView()
{
    if (isViewUpToDate)
        return;

    // Logic goes here

    isViewUpToDate = true;
}

static void Main()
{
    Application.Idle += (sender, eventData) => MainForm.Instance?.CheckDataGridSelectionView();

    // ...
}
AdamRossWalker
  • 294
  • 1
  • 10