c# - 使用 ListView 的 WinRT ObservableCollection 删除操作

标签 c# listview windows-runtime

我正在开发一个 WinRT 8.1 应用程序,我在其中将我的 ListView 控件绑定(bind)到 ObservableCollection

            <ListView x:Name="DetailsViews" HorizontalAlignment="Center" VerticalAlignment="Top" Grid.Row="3" Width="395">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Grid x:Name="grid" Holding="grid_Holding" Height="60" Width="395">
                        <FlyoutBase.AttachedFlyout>
                            <MenuFlyout>
                                <MenuFlyoutItem x:Name="DeleteButton" Text="delete" Click="DeleteSelectedItem"/>
                            </MenuFlyout>
                        </FlyoutBase.AttachedFlyout>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="70"/>
                            <ColumnDefinition Width="1*"/>
                            <ColumnDefinition Width="40"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock HorizontalAlignment="Center" FontSize="32" TextAlignment="Center" Text="{Binding DetailTitle}" VerticalAlignment="Center"/>
                        <TextBox HorizontalAlignment="Left" FontSize="32" Height="{Binding ElementName=grid, Path=Height}" Text="{Binding DetailValue}" TextWrapping="Wrap" VerticalAlignment="Center" Grid.Column="1" Width="320"/>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

这是我的代码隐藏文件。

myList = new ObservableCollection<Person>();

myList.Add(new Person() { DetailTitle = "Key", DetailValue = "Value"  });

DetailsViews.ItemsSource = myList;

我需要知道如何从 ObservableCollection 中删除项目,以便在每次删除时更新 UI。这是我的删除代码,但它不起作用,因为如果我在此处放置断点,SelectedIndex 每次都会返回 -1。

private void DeleteSelectedItem(object sender, RoutedEventArgs e)
{
    this.myList.RemoveAt(this.DetailsViews.SelectedIndex);
}

如何更新 UI 以及可能出现的问题?

最佳答案

好的,这是我能想到的最基本的示例,使用基本的空模板,它可以工作,这就是为什么@KooKiz 说您的代码看起来不错。

因此,您至少需要发布声明 ListView 的部分,以便获得解决问题的帮助。

XAML

<Page
    x:Class="App1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <ListView Name="ItemsView" ItemsSource="{Binding items}"/>
        <Button Click="Button_Click" Content="Test Remove"></Button>
    </Grid>
</Page>

代码隐藏

using System;
using System.Collections.ObjectModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace App1
{
    public sealed partial class MainPage : Page
    {
        ObservableCollection<String> items = new ObservableCollection<string>();

        public MainPage()
        {
            this.InitializeComponent();

            items.Add("First Item");
            items.Add("Second Item");
            items.Add("Third Item");
            items.Add("Fourth Item");

            ItemsView.ItemsSource = items;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            items.RemoveAt(ItemsView.SelectedIndex);
        }
    }
}

编辑

好的,感谢您的代码更新,我能够找出问题所在,我为您提供了一个快速解决方案,如果它不是您想要的,我还会提供一些建议:)

解释

我想你有一个处理持有事件的方法是这样的:

private void grid_Holding(object sender, Windows.UI.Xaml.Input.HoldingRoutedEventArgs e)
{
    FlyoutBase.ShowAttachedFlyout(sender as FrameworkElement);
}

所以发生的事情是您在用手指按住时触发了 holding 事件,但此事件不会选择任何项目,因为项目是在触摸/点击时选择的,这就是为什么当您单击删除时它是没有选定的元素。

我已经测试过用单点触摸选择一个项目然后做握持部分并且它工作正常。

解决方案

现在我们知道发生了什么,有不同的解决方案,具体取决于您最终想要实现的目标,为简单起见,我将假设最容易实现的 :)。

让我们假设除了删除它们或导航(不需要选择 ListView 项目)之外,您不以任何其他方式使用选定的项目

所以首先我们在 XAML 中将 ListView 编辑为 SelectionMode="None" (请注意,给定的修复程序在没有它的情况下仍然有效,但它可能会使用户感到困惑)

<ListView x:Name="DetailsViews" 
          SelectionMode="None"
          HorizontalAlignment="Center"
          VerticalAlignment="Top" 
          Grid.Row="3" 
          Width="395">

然后您需要在后面的代码中添加一个属性来保存所选项目的值,因为您不会使用 ListView 的选择(索引或项目)。

public Person SelectedItem { get; set; }

然后我们需要稍微修改删除和持有处理程序以使用新属性

private void DeleteSelectedItem(object sender, RoutedEventArgs e)
{
    //items.RemoveAt(DetailsViews.SelectedIndex);
    items.Remove(SelectedItem);
}

private void grid_Holding(object sender, Windows.UI.Xaml.Input.HoldingRoutedEventArgs e)
{
    SelectedItem = (sender as FrameworkElement).DataContext as Person;
    FlyoutBase.ShowAttachedFlyout(sender as FrameworkElement);
}

所以这些现在做的是:删除项目现在通过对象而不是索引删除

对象来自持有处理程序,您在其中将所选项目设置为当前按下的元素的 DataContext(即 ListView 元素的 DataContext,即 Person)

我会建议您添加一些防御性编程并进行一些检查以保护您的程序免受崩溃/异常的影响。如果您正在做测试项目以外的任何事情,我还建议您学习一些关于如何使用 MVVM 的类(class)。

欢呼和快乐的编码;)

关于c# - 使用 ListView 的 WinRT ObservableCollection 删除操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33327574/

相关文章:

c# - 使用时间跨度作为字典中的键?

C# 创建事件处理程序 'method name expected' 错误

c# - TransactionScope 在处置前已中止交易

android - 带有自定义 ArrayAdapter 的 ListView 不显示项目

android - 列表适配器的notifyDataSetChanges,只修改部分 View

java - 如何更改 ListView 项目数?

c# - 如何禁用 WinRT 的 HttpWebRequest 中的 “Expect: 100 continue” header

c# - 如何为 WPF 4 使用 WinRT 转换

c# - WinRT 应用程序和区域设置。根据用户的区域设置格式化日期和数字的正确方法?

c# - xamarin 表单中的异步 Task<T> 问题