First of all, we'll assume that the DataGrid we are using is bound to a list of classes called DummyDataItem as below:
Expand|Select|Wrap|Line Numbers
- class DummyDataItem
- {
- public string Name { get; set; }
- public DummyDataItem(string name)
- {
- Name = name;
- }
- }
Ok so here is one of the first methods i tried...
Expand|Select|Wrap|Line Numbers
- public void InvertA()
- {
- foreach (object o in dataGrid1.Items)
- {
- DataGridRow row = o as DataGridRow;
- if (row.IsSelected == true)
- {
- row.IsSelected = false;
- }
- else
- {
- row.IsSelected = true;
- }
- }
- }
At first glance this method may seem completely reasonable, we do a light cast so that we can check weather the row is selected or not, then invert it on an item by item basis. However give it a run, and you'll soon find that items in the DataGrid actually can't be cast to a DataGridRow! hmm, we'll have to try something else...
Expand|Select|Wrap|Line Numbers
- public void InvertB()
- {
- var selected = dataGrid1.SelectedItems;
- dataGrid1.SelectAll();
- for (int x = 0; x < selected.Count; x++)
- {
- dataGrid1.SelectedItems.Remove(selected[x]);
- }
- }
A shorter sub, looks neat and tidy, and this time we get no runtime errors :D but oops, now it's selecting a load of random ones... wonderful. Clearly something is going wrong, and the more experienced of you may notice that "var selected" actually only references the selected items. This means when we iterate over the selected items, the list has changed and keeps on changing during the loop, we can't use this.
Lastly the way that works, from my last example, you can see that we were half way there, however we need to work with a reference list that does not change as we are inverting. So if we cast each selected item to it's base class, and add one of the classes properties preferably a string as strings are read only to a list, we can keep track of which items to remove from the selection (after select all).
Expand|Select|Wrap|Line Numbers
- public void InvertC()
- {
- List<string> names = new List<string>();
- foreach (object o in dataGrid1.SelectedItems)
- {
- names.Add((o as DummyDataItem).Name);
- }
- dataGrid1.SelectAll();
- foreach (object z in dataGrid1.Items)
- {
- if (names.Contains<string>((z as DummyDataItem).Name))
- {
- dataGrid1.SelectedItems.Remove(z);
- }
- }
- }
In this example, we grab the name from each DummyDataItem that is currently selected, select all the items, then pick out based on a name comparison which items do not belong in the DataGrid's SelectedItems property.
For now this seems the most sensible way to accomplish this task, I hope someone finds this useful, and If anyone has any better solutions, please feel free to share them also.
Aimee Bailey.