dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.04k stars 1.73k forks source link

Changing visibility on an SwipeItem causes multiple items to be executed #7580

Open pekspro opened 2 years ago

pekspro commented 2 years ago

Description

Let's say you have a to do list. There are two swipe commands for each item:

Only one option is visible at the time. If you execute the first swipe item, then the second one will become visible and then this is executed as well.

Steps to Reproduce

  1. Create a new MAUI app.
  2. Change MainPage.xaml to:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:v="clr-namespace:MauiIssues"
             x:Class="MauiIssues.MainPage"
             >
    <Grid>
        <CollectionView ItemsSource="{Binding Issues}">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <SwipeView Threshold="250">
                        <SwipeView.LeftItems>
                            <SwipeItems Mode="Execute">
                                <SwipeItem Text="Set as not completed"
                                           IsVisible="{Binding IsCompleted}"
                                           Command="{Binding CommandToggle}"
                                           BackgroundColor="Red" />

                                <SwipeItem Text="Set as completed"
                                           IsVisible="{Binding IsNotCompleted}"
                                           Command="{Binding CommandToggle}"
                                           BackgroundColor="Green" />
                            </SwipeItems>
                        </SwipeView.LeftItems>

                        <HorizontalStackLayout Spacing="20">
                            <Label Text="{Binding Title, Mode=OneWay}" />
                            <Label Text="Completed: " />
                            <Label Text="{Binding IsCompleted}" />
                        </HorizontalStackLayout>
                    </SwipeView>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </Grid>
</ContentPage>
  1. Change MainPage.cs to:
using System.Collections.ObjectModel;
using System.Windows.Input;

namespace MauiIssues;

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();

        BindingContext = this;
    }

    public class Issue : BindableObject
    {
        public string Title { get; set; }
        public bool IsCompleted { get; set; } = true;
        public bool IsNotCompleted => !IsCompleted;

        public ICommand CommandToggle { get; }

        public Issue()
        {
             CommandToggle = new Command(() => Toggle());
        }

        public void Toggle()
        {
            IsCompleted = !IsCompleted;
            System.Diagnostics.Debug.WriteLine($"{DateTime.Now.ToString("HH:mm:ss")} Setting {Title} to {IsCompleted}");
            OnPropertyChanged(nameof(IsCompleted));
            OnPropertyChanged(nameof(IsNotCompleted));
        }
    }

    public ObservableCollection<Issue> Issues { get; } = new ObservableCollection<Issue>();

    protected override void OnAppearing()
    {
        base.OnAppearing();

        Issues.Add(new Issue { Title = "Issue 1", IsCompleted = false });
        Issues.Add(new Issue { Title = "Issue 2", IsCompleted = true });
        Issues.Add(new Issue { Title = "Issue 3", IsCompleted = false });
        Issues.Add(new Issue { Title = "Issue 4", IsCompleted = true });
    }
}
  1. Run the application on Android (swipe doesn't work on Windows).
  2. Swipe first item to set it to completed. This will work.
  3. Swipe second item to set it not completed. This will happen, but immediately it will also be set to completed. You can see this in the logs.

Full sample: https://github.com/pekspro/MauiIssues/tree/7580_Changing_visibility_on_SwipeItem_multiple_execution

Version with bug

6.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

Android, I was not able test on other platforms

Affected platform versions

Android 11

Did you find any workaround?

In the mentioned scenario, just use one command, and use converters to change to content. But I guess there are other cases where this is not possible.

Relevant log output

No response

ToolmakerSteve commented 2 years ago

Another possible workaround is to move OnPropertyChanged lines to an event handler attached to SwipeEnded event.

kristinx0211 commented 2 years ago

verified repro with above repro project on windows, swipe doesn't work. repro project: MauiIssues.zip on android:

  1. set it to completed. this can work
  2. set to not completed, the event Toggle is executed twice, first is set to false, and immediately it is set to true. image
jsuarezruiz commented 2 years ago

"swipe doesn't work on Windows"

Are you using a touch screen?.

pekspro commented 2 years ago

"swipe doesn't work on Windows"

Are you using a touch screen?.

I meant that touch events doesn't work with mouse in Windows :-) That's another issue :-)

ghost commented 1 year ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

pekspro commented 1 year ago

I've updated sample application to .NET 7. The same issue remains.

XamlTest commented 1 year ago

Verified this on Visual Studio Enterprise 17.6.0 Preview 7.0. Repro on Android 13.0 with below Project: 7580.zip

Swipe second item to set it not completed. It will execute twice. image

jiangjiali commented 7 months ago

SwipeView 本身就是用于触碰而设计的吧。