6

I have a WPF DataGrid theDataGrid bound to a DataSet ds containing a table. I want to enable the user to remove lines by first selecting them in the grid and then pressing a button (positioned somwhere outside of the datagrid). I finally arrived at the following lines of code which do what I want, but which I consider rather ugly:

  DataSet ds = new DataSet();
        ...
  // fill ds somehow
        ...
  private void ButtonClickHandler(object Sender, RoutedEventArgs e) 
  {
        List<DataRow> theRows = new List<DataRow>();
        for (int i = 0; i < theDataGrid.SelectedItems.Count; ++i)
        {
            // o is only introduced to be able to inspect it during debugging
            Object o = theDataGrid.SelectedItems[i];
            if (o != CollectionView.NewItemPlaceholder)
            {
                DataRowView r = (DataRowView)o;
                theRows.Add(r.Row);
            }
        }
        foreach(DataRow r in theRows) 
        {                
            int k = ds.Tables["producer"].Rows.IndexOf(r);
            // don't remove() but delete() cause of update later on
            ds.Tables[0].Rows[k].Delete();
        }
   }

Is there a better way to do this? E.g. one which needs only one loop and without having to check for the NewItemPlaceHolder explicitly, or possible a more efficient way to access the rows which are to be deleted?

(I already figured out that I must not remove anything from the ds in the first loop, since then theDataGrid.SelectedItems.Count changes everytime the loop is executed...)

1
  • i have a solution do you want that i add it?? Commented Jun 17, 2013 at 10:21

3 Answers 3

2

In order to remove row selected on button click you can try:

private void ButtonClickHandler(object sender, RoutedEventArgs e)//Remove row selected
     {
      DataRowView dataRow = (DataRowView)dataGridCodes.SelectedItem; //dataRow holds the selection
      dataRow.Delete();                    
     }
Sign up to request clarification or add additional context in comments.

Comments

0

I think it works by just one loop:

int count=theDataGrid.SelectedItems.Count;
int removedCount=0; 
while (removedCount < count)
{
    try{
         Object o = theDataGrid.SelectedItems[0];
    }
    catch{ break;}

    if (o == CollectionView.NewItemPlaceholder)
    continue;

    DataRowView r = (DataRowView)o;
    r.Row.Delete();
    removedCount++;
}

4 Comments

Uhmm, thanks but no. The foreach loop you added after 'Edit' was my first 'solution', actually. It results in an unhandled exception. This is what I was referring to in the last line of my question, the one in parentheses. The SelectedItems collection changes during the loop and the foreach counter refers to something invalid (I think). I'd expect the same with the first approach.
@Thomas You are right about the second one, but at least I'm sure that Collection Modified Exception will not be thrown in the first one.
It crashes because you increase index which eventually becomes larger than the (current) SelectedItems.Count. It will probably work if you retrieve SelectedIndex[0] each time. But, to be honest, with a manually updated counter it is not nicer than my code. What I would like to have is a one liner like your second suggestion, but one which does not crash ;-)
@Thomas again you are right; sorry for the errors; As you said I should 've used SelectedIndex[0]; I think one loop it is more efficient, so try to use it :)
0

You can remove the double loop by iterating backwards :

private void ButtonClickHandler(object Sender, RoutedEventArgs e) {
    for (int i = theDataGrid.SelectedItems.Count-1; i>=0; --i)
        if (theDataGrid.SelectedItems[i] != CollectionView.NewItemPlaceholder)
            ds.Tables[0].Rows[i].Delete();
   }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.