justinf
justinf

Reputation: 1298

Removing entries from an ObservableCollection by selecting them in a data grid

I have a data grid that is bound to an observable collection. I want to select a few rows in the data grid and click a button and have those rows removed from the collection .

When I try it my way I get an error “Collection was modified; enumeration operation may not execute.

I know the error is caused, because I am looping though an altering the collection I did some research and tried to apply what I found but I can seem to get it to work.

How I make the collection and bind it to the Datagrid

 ObservableCollection<XbmcInfo> SelectedShowSeason = new ObservableCollection<XbmcInfo>();
 ToCopy.DataContext = SelectedShowSeason;

How I try remove values from the collection

  private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            var x = ToCopy.SelectedItems;
            foreach (XbmcInfo f in x)
            {
                string ShowName = f.ShowName;
                string ShowSeasonNumber = f.Number;

                var Selected = SelectedShowSeason.FirstOrDefault(u => u.ShowName == ShowName && u.Number == ShowSeasonNumber);

                SelectedShowSeason.Remove(Selected);
            }
        }

This is the XML for the datagrid

 <DataGrid Name="ToCopy" AutoGenerateColumns="False" ItemsSource="{Binding}"  Margin="0,0,0,51" Grid.Row="2" Grid.ColumnSpan="3" IsReadOnly="True" CanUserResizeRows="False" CanUserReorderColumns ="False"  IsSynchronizedWithCurrentItem="True">
            <DataGrid.Columns>
                <DataGridTextColumn Header="ShowName" Width="*" Binding="{Binding Path=ShowName}" />
                <DataGridTextColumn Header="Season" Width="50" Binding="{Binding Path=Number}" />
                <DataGridTextColumn Header="Path" Width="*" Binding="{Binding Path=Path}"/>
            </DataGrid.Columns>
   </DataGrid>

My Class

public class XbmcInfo
    {
        public string ShowName
        {
            get;
            set;
        }

        public string Number
        {
            get;
            set;
        }

        public string Path
        {
            get;
            set;
        }
    }

Upvotes: 0

Views: 132

Answers (2)

sexta13
sexta13

Reputation: 1568

The way I would do it:

  • XbmcInfo: add a property IsSelected bound to selected property in Datagrid.record
  • Button_Click_1: Iterate in SelectedShowSeason.Where(x=>x.IsSelected); and then remove the item(s).

Other way, would be to iterate from last to first:

        for(int i=x.Count; i>0;i--) { 
 string ShowName = x[i].ShowName;
                string ShowSeasonNumber = x[i].Number;

var Selected = SelectedShowSeason.FirstOrDefault(u => u.ShowName == ShowName && u.Number == ShowSeasonNumber);

                        SelectedShowSeason.Remove(Selected);
    }

===================EDIT===================

To bind the property to the datagrid, you can add a style for the items in datagrid.

Something like this:

<Datagrid..... ItemContainerStyle = {StaticResource ItemsSelected} />

This "ItemsSelected" style would be something like this:

<Style>
<Setter Property = "IsSelected" Value = "{Binding Path=IsSelected}"/>
</Style>

What you are doing is saying that the items inside the datagrid , which have a IsSelected, binds to your property.

Give it a try...the code can have some errors but the genesis of it is there :)

Regards,

Upvotes: 0

Eli Arbel
Eli Arbel

Reputation: 22739

I believe the problem is modifying the SelectedItems collection while iterating it.

Try replacing the line:

var x = ToCopy.SelectedItems;

With:

var x = ToCopy.SelectedItems.OfType<XbmcInfo>().ToArray();

Upvotes: 1

Related Questions