简体   繁体   中英

WinRT ObservableCollection delete operation with ListView

I'm developing a WinRT 8.1 application in which I'm binding my ListView control to the ObservableCollection as this

            <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>

Here is my code behind file.

myList = new ObservableCollection<Person>();

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

DetailsViews.ItemsSource = myList;

I need to know, that how to delete items from the ObservableCollection so that on each deletion, it updates the UI. Here is my delete code but it is not working because SelectedIndex is returning -1 each time if I put a breakpoint there.

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

How do I update the UI and what problem it could be?

Ok here's the most basic example that I can think of with the basic empty template, and it works, that's why @KooKiz said that your code looks OK.

So you'll need to post at least the part that you are declaring the ListView in order to get help with your issue.

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>

Code Behind

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);
        }
    }
}

EDIT

OK thanks to the update of your code, I was able to find out what's wrong with it and I have a quick solution for you, and some advice if it's not exactly what you want from it :)

Explanation

I imagine you have a method handling the holding event like this:

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

so what happens is you fire the holding event while holding with your finger but this event does not select any item, because items are selected on touches/clicks , and that's why when you click delete it's without selected element.

I've tested to select an item with single touch and then do the holding part and it's working correctly.

The solution

So now that we know what is happening there are different solutions depending on what you want to achieve at the end, for simplicity I'll assume the easiest to implement :) .

Lets assume you don't use selected items in any other way than to delete them or to navigate (no selection of list view items needed)

So first we edit the ListView in XAML to be SelectionMode="None" (note that the given fix works without it but it might confuse the user)

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

then you need to add a property in your code behind to hold the value of the selected item because you're not going to use the selection (index or item) of the ListView.

public Person SelectedItem { get; set; }

and then we need to slightly modify the deletion and the holding handlers to use the new property

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);
}

So what these do now is: Delete item now remove by the object not by index

And the object is coming from the holding handler where you set the selected item to be the DataContext of the current pressed element (which is the DataContext of the ListView element, which is Person)

I would advice you to add some defensive programming and do some checks to guard your program from crashes/exceptions. Also I'd advice you to go over some courses on how to use MVVM if you are doing anything other than a test project.

Cheers and happy coding ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM