views:

7284

answers:

5

Is there a way to turn off the automatic selection of the first row in the built-in DataGrid in Silverlight?

We build a lot of functionality based off the user selecting a row in a data grid. The automatic firing of SelectionChanged when databinding or sorting is really causing us issues. We have tried to put some guards around the selection, but can't seem get all problems covered.

For example, if you have DataGrid in a tab of a TabControl that is not shown when loading the screen and the DataGrid has a binding to a property of the DataContext that is a list of objects. The grid is not databound until the tab is shown. Is there an event telling us that the grid is databinding? Shouldn't the default behavior of databinding be not to select a row?

Thanks Mike

+1  A: 

Mike,

I have solved this problem by wrapping the windows control, and catching the selection changed event of the wrapped windows grid.

In your control, hook up the Loaded event of your control, and when it is loaded, set a boolean private member variable to true. Then when you are catching the inner data grid's selection changed event, only raise your own selection changed event if you control is loaded. When this is done, you can now go back to the OnApplyTemplate sub, and set your inner data grid's selected index to -1 and selected item to nothing. Since the setting of the index and item will happen before your control is finished loading, the selection changed event will not fire. I have tried this in both a tabbed and non-tabbed environment, and it seems to work without issue. Now on to a little bit harder problem, you may have noticed that when you sort the windows data grid (while it is data bound to an ItemsSource) it always selects the top item of the displayed data. This will of course, fire the selection changed event, and move to an item that was not previously selected, and as far as I can see, shouldn't be selected. To handle this, you will have to do a little bit more tricky coding. If you notice, when you catch the inner grid's selection changed event, and look at its selected item, there are only a few cases where the selected item is not set to anything, those are, when there is no longer an item selected (ie. the selection is cleared), or when (HINT) the columns are sorting. When you are sorting, there are two events that fire, first is the de-selection of the item (SelectedItem is Nothing), and the second is the selection of the top item in the list (SelectedIndex 0). Now, if you were to put a flag in the event handler for the inner grids selection changed event, and caught the fact that the item is nothing, you could keep track of the prior selected item, and then set the inner data grid's selected item to the previously selected item.

This solves the problem decently well, and as always there may be undesired results while wrapping a windows control, but as far as I can tell, this seems to be the only way to get around the first row being selected on load problem. I can only imagine, however, that this is going to be fixed by M$ at some point.

I hope this helps,

Thanks,

Scott

Scott
+2  A: 

Hi Mike,

Have you tried setting a boolean field (ex. bool dataGridFirstLoad) which you set to false in your User Control's constructor.

Then on the SelectionChanged event of the DataGrid, check if dataGridFirstLoad is false. If false set to true and set the SelectedItem to null.

Hope this helps.

ptio
A: 

The code below should do it (set JustRefreshed to true whenever you update/refresh the grid):

 int LastSelectedIndex = -1;
 bool JustRefreshed = false;

        private void dataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (JustRefreshed)
            {
                JustRefreshed = false;
                dataGrid.SelectedIndex = LastSelectedIndex;
                return;
            }
            if (e.AddedItems.Count > 0)
            {
                LastSelectedIndex = dataGrid.SelectedIndex;
                        }    
                //Your logic comes here...
            }
        }
+1  A: 

this is similar to the posts above (and hashes out Paulo T's suggestion). This works well. //set the selectionchanged handler in the xaml or in the constructor //I have 2 grids on my page so I create one boolean property for each

private bool IsFirstLoad { get; set; }
private bool IsFirstLoadDetails { get; set; }
public BookDisplay()
{
  //code here
  this.IsFirstLoad = true;
  this.IsFirstLoadDetails = true;
  BindBooks(); //define this function (not in this snippet for the sake of brevity)
}
private void GridBooks_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
  if (this.IsFirstLoad)
  {
    GridBooks.SelectedItem = -1;
    this.IsFirstLoad = false;
  }
  else
  {
    //do your stuff
  }
}
private void GridBooksWithDetails_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
  if (this.IsFirstLoadDetails)
  {
     GridBooksWithDetails.SelectedItem = -1;
     this.IsFirstLoadDetails = false;
  }
}
Kevin
A: 

Since the code for the DataGrid was available from Microsoft, we removed the selection so we didn't have to work around it. I believe this is no longer an issue with the Silverlight 3.0 grid.

Mike Schall