如何从GridView获取选定的项目

时间:2018-09-28 04:45:23

标签: xaml uwp uwp-xaml

我正在制作图书馆管理软件。这是XAML:

<CommandBar Grid.Row="0">
        <AppBarButton Icon="Add" 
                      Label="New Book"
                      Click="NewBook_Click"/>

        <AppBarButton Icon="Delete"
                      Label="Remove a Book"
                      Click="DeleteBook_Click"/>
    </CommandBar>

    <GridView x:Name="AllBooks_GridView"
              ItemsSource="{x:Bind Path=ViewModel.Books, Mode=OneWay}"
              ScrollViewer.VerticalScrollBarVisibility="Visible"
              ScrollViewer.VerticalScrollMode="Enabled"
              ScrollViewer.HorizontalScrollMode="Disabled"
              Grid.Row="1"
              SelectionMode="Multiple">

        <GridView.ItemTemplate>
            <DataTemplate x:DataType="data:Book">

                <StackPanel Margin="10" HorizontalAlignment="Center">
                    <Image Width="200" Height="200" Source="{x:Bind Path=CoverImageLocation, Mode=OneWay}" />
                    <Grid HorizontalAlignment="Stretch">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition />
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <StackPanel>
                            <TextBlock FontSize="16" 
                                       Text="{x:Bind Path=Title, Mode=OneWay}" 
                                       TextTrimming="WordEllipsis"/>
                            <TextBlock FontSize="10" 
                                       Text="{x:Bind Path=Author, Mode=OneWay}" 
                                       Margin="0, 3, 0, 0" 
                                       TextTrimming="WordEllipsis"/>
                        </StackPanel>
                        <TextBlock FontSize="20" 
                                   Text="{x:Bind Path=Quantity, Mode=OneWay}"
                                   Grid.Column="1" 
                                   VerticalAlignment="Bottom"                                        
                                   Margin="20, 0, 0, 0"
                                   HorizontalAlignment="Left"/>
                    </Grid>
                </StackPanel>

            </DataTemplate>
        </GridView.ItemTemplate>

    </GridView>

我想选择多个栏,并在按下第二个应用栏按钮时将其删除。这是DeleteBook_Click函数:

private void DeleteBook_Click(object sender, RoutedEventArgs e)
{
   var books = AllBooks_GridView.SelectedItems;

   foreach (var b in books)
   {
      var book = b as Book;

      DataAccess.DeleteBook(book.Title);
      ViewModel.Books.Remove(book);
   }
}

这是我的应用程序的屏幕截图:

enter image description here

当我单击删除图标时,只会删除第一本书。尽管两个都被选中。我在做什么错了?

3 个答案:

答案 0 :(得分:3)

您要在迭代集合的项目时对其进行更改。

AllBooks_GridView.SelectedItems是集合,当您在foreach循环中对其进行迭代时,可以通过调用

对其进行更改。
ViewModel.Books.Remove(book);

此调用之后,将刷新GridView以反映您对ViewModel所做的更改,并且SelectedItems集合中的项目变少了。并且在下一次迭代中,SelectedItems将不再包含您所期望的两本书,而是仅包含一本书。而且由于代码在下一次迭代中试图从集合中删除第二本书,所以什么也没有发生,循环终止。

这里是解决方法:

//Now the books collection is no longer bound to the SelecteItems of the GridView, 
//it is 'immutable' in the foreach loop
List<Book> books = new List<Book>(); 
foreach (var item in AllBooks_GridView.SelectedItems)
    books.Add(item as Book); 

foreach (var book in books)
{
   DataAccess.DeleteBook(book.Title);
   ViewModel.Books.Remove(book);
}

答案 1 :(得分:2)

原因在Kennyzx的答案中给出。

要使其正常工作,请执行以下操作:

private void DeleteBook_Click(object sender, RoutedEventArgs e)
{
   var books = AllBooks_GridView.SelectedItems.ToList(); // this will create a new list

   foreach (var b in books)
   {
      var book = b as Book;

      DataAccess.DeleteBook(book.Title);
      ViewModel.Books.Remove(book);
   }
}

答案 2 :(得分:1)

Books集合中删除一本书时,ObservableCollection会通知数据绑定有关更改的信息,该更改将依次修改SelectedItems集合。

通常,这会引发异常,但在这种情况下,不会,因为删除第一项只是将第二项移到其位置(减小了集合的大小)并向前枚举而被“掩盖”只检查下一个索引是否存在,因为不存在,循环不会继续。您可以通过选择三项来确认这一点-第一个将被删除,第二个将被跳过,但第三个将被再次删除。

最简单的解决方案是确保迭代除SelectedItems属性以外的其他集合。最便宜的实现方法是在第一行使用LINQ ToArray扩展名。

var books = AllBooks_GridView.SelectedItems.ToArray();

这将创建一个新数组,其中包含所有选中的书,然后当您从ViewModel.Books中删除并更新SelectedItems时,不再重要,因为我们的books变量是一个不同实例。