Ok today I came across one of the oddest problems so far in my programming life, I was building an application not to dissimilar to a file explorer, and I had the need to invert the row selection on the DataGrid control, something easy you say? well give it a go and you'll soon come across the same issue. The problem was that there is no specified way to do this, plus a search on Google showed that not many people have needed this yet, so I was stuck having to write a routine myself, this insight is the result of my efforts in hope that no one else has to go through hours trying to do the same thing.
First of all, we'll assume that the DataGrid we are using is bound to a list of classes called DummyDataItem as below:
Ok so here is one of the first methods i tried...
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...
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).
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.
First of all, we'll assume that the DataGrid we are using is bound to a list of classes called DummyDataItem as below:
Code:
class [B]DummyDataItem[/B] { public string Name { get; set; } public DummyDataItem(string name) { Name = name; } }
Ok so here is one of the first methods i tried...
Code:
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...
Code:
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).
Code:
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.
Comment