Reputation: 248
I have created an application in Visual Studio (C#) that makes use of a datagridview. Now, when I assign the DataSource of that datagridview, it automatically selects the first row, and executes my code for selection. Since I frequently reassign that datasource, this is not desireable. Is there any way to change it so it doesn't automatically make that first select, and only relies on the user's selections?
Thanks!
In response to the comment of Darshan Joshi: Apart from the auto-generated code, the only thing altered on the datagridview is setting AutoGenerateColumns to false, and setting the DataSource property. I've placed a MessageBox.Show in my selectionchanged delegate, and it seems it even gets called thrice every time the datasource is set. Once just before the data is loaded, and twice after.
I can't set selected to false on load, since the datasource is set after certain user actions, not on initialization.
Upvotes: 11
Views: 24342
Reputation: 1
To paraphrase @computerGuyCJ there is no single answer that will work in all circumstances (including both his and mine). Also, some of the answers are truly ludicrous and unhelpful.
Assuming you are not using VirtualMode, the trick that worked for me is to capture the first row that is added, via the CollectionChanged event on the Rows collection:
public MyDataGridView() =>
Rows.CollectionChanged += Rows_CollectionChanged;
private DataGridViewRow? _pendingSelection = null;
private void Rows_CollectionChanged(object? sender, CollectionChangeEventArgs e)
{
// Assume that each time we add a first row it will eventually be selected
if (e.Action == CollectionChangeAction.Add &&
e.Element is DataGridViewRow row && row.Index == 0)
_pendingSelection = row;
}
Then, when the SelectionChanged event for that row eventually occurs, the code silently "swallows" it:
protected override void OnSelectionChanged(EventArgs e)
{
// If we automatically selected the row we did NOT want to select...
if (_pendingSelection != null && _pendingSelection.Selected)
{
// Do not come this way again
DataGridViewRow row = _pendingSelection;
_pendingSelection = null;
// Clear its selection
row.Selected = false;
// Return without raising the SelectionChanged event
return;
}
base.OnSelectionChanged(e);
}
As mentioned, this solution is by no means bullet-proof. It will fail if the control is not data bound. It will fail if the user adds a first row. It will probably fail in other circumstances as well. It works for me, for a data bound grid, where the user cannot add rows. I share it in case you have a similar circumstance.
The only real solution is for Microsoft to add a "DoNotAutoselect" property, to expose an event related to auto-selection, or to at least expose more events related to the data binding process (beyond DataBindingComplete).
The actual timing of auto-selection appears to be a complex interplay depending on the mode of the control (e.g. VirtualMode), its visibility, and the mechanics of databinding. Perhaps there is a way to cover every possible combination, but my guess is that any such solution would be flaky, complex, and prone to breaking.
Anyhow, good luck! I hope this helps someone and doesn't simply add to the confusion.
Upvotes: 0
Reputation: 1
The solution is based in put the .ClearSelection() the neccesary times. If you check the method while enter, you can intuitive when is necessary insert, in my case, i load my rows in my data grid view when i click button on menu in my aplication, immediatly show the form and the first row is selected, but if i check the times SelectionChanged() is enter, i can clean selection, but only the neccesary times.
Private veces_entrando As Integer = 0
Private Sub DGVLista_SelectionChanged(sender As Object, e As EventArgs) Handles DGVLista.SelectionChanged
veces_entrando = veces_entrando + 1
If veces_entrando < 2 Then
DGVLista.ClearSelection()
End If
End Sub
Upvotes: 0
Reputation: 3107
For my case, a more simple solution was enough, in my DataGridView_DataBindingComplete
handler:
DataGridView.ClearSelection();
if (DataGridView.Focused)
DataGridView.DataBindingComplete -= DataGridView_DataBindingComplete;
Upvotes: 0
Reputation: 51
I think the simplest solution is to remove the eventhandler, assign the new datasource, clear the selection and reassign the eventhandler:
private void updateDataGridViewDataSource(%whatevertype% %whatever%) {
dataGridView1.SelectionChanged -= new System.EventHandler(this.dataGridView1_SelectionChanged);
dataGridView1.DataSource = %whatever%
dataGridView1.ClearSelection();
dataGridView1.SelectionChanged += new System.EventHandler(this.dataGridView1_SelectionChanged);
}
Upvotes: 1
Reputation: 767
Your experience may vary, but in my work I frequently fight this when the grid first loads, and although many solutions have been found to be acceptable (and far more are just ludicrous), they don't all work in every scenario. The one solution I find that works the most (for me, again your experience and scenarios may vary) is handling DataGridView.VisibleChanged:
public ThingWithGrid() {
Grid.VisibleChanged += Grid_VisibleChanged;
}
private void Grid_VisibleChanged(object sender, EventArgs e)
{
UpdateSelectedRows(InitialSelection);
Grid.VisibleChanged -= Grid_VisibleChanged;
}
Upvotes: 0
Reputation: 1
This worked for me:
Deregister the SelectionChanged event just before binding the data and then re-register the event. Maybe you should delete the registration of the event in the designer and register the event manually in your code.
myDGV.SelectionChanged -= new System.EventHandler(this.myDGV_SelectionChanged);
Upvotes: 0
Reputation: 11
Make sure your are NOT calling the method to load the data from the form constructor. If you call it from the Form.load()
also after the myDataGridView is loaded do this
myDataGridView.Rows[0].Selected = false;
Upvotes: 0
Reputation: 71
Just add SelectedItem="-1", this will do the trick
<DataGrid Name="dataGrid" SelectedItem="-1" />
Upvotes: -1
Reputation: 373
You should call: ClearSelection after event: DataBindingComplete
Upvotes: 9
Reputation: 125
To load the grid without any selection, you can use this code snippet.
GridView.CurrentCell = null;
This will load it plain, without any selection. Add this after assigning data-source to the grid.
Upvotes: 0
Reputation: 280
I had the same problem and here is my solution.
The tricky part was finding where to clear the selection... We can only clear the selection after the selection has been set by the DataGridView. At first the selection is only ready to be cleared in the Form.Load event, but subsiquent settings of the DataGridView.DataSource the selection is ready to be cleared straight after the DataSource assignment.
public class DataGridView_AutoSelectSuppressed : DataGridView
{
private bool SuppressAutoSelection { get; set; }
public DataGridView_AutoSelectSuppressed() : base()
{
SuppressAutoSelection = true;
}
public new /*shadowing*/ object DataSource
{
get
{
return base.DataSource;
}
set
{
SuppressAutoSelection = true;
Form parent = this.FindForm();
// Either the selection gets cleared on form load....
parent.Load -= parent_Load;
parent.Load += parent_Load;
base.DataSource = value;
// ...or it gets cleared straight after the DataSource is set
ClearSelectionAndResetSuppression();
}
}
protected override void OnSelectionChanged(EventArgs e)
{
if (SuppressAutoSelection)
return;
base.OnSelectionChanged(e);
}
private void ClearSelectionAndResetSuppression()
{
if (this.SelectedRows.Count > 0 || this.SelectedCells.Count > 0)
{
this.ClearSelection();
SuppressAutoSelection = false;
}
}
private void parent_Load(object sender, EventArgs e)
{
ClearSelectionAndResetSuppression();
}
}
Hope this helps.
Upvotes: 2
Reputation: 11144
you can deselect it in your form_load event like
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.Rows[0].Selected = false;
}
Upvotes: 0