How to use ResetSwipe and conditionally disable swiping with sfListView and MVVM

Hi, I hope you can help.

I am using sfListView with the MVVM model. The listview is using a RightSwipeTemplate and the user can take a photo using a command bound to a GestureReconizer:

<Grid.GestureRecognizers>
  <TapGestureRecognizer Command="{Binding Source={RelativeSource AncestorType={x:Type viewModels:TestResultViewModel}}, Path=TakePhotoCommand}" CommandParameter="{Binding .}" />
</Grid.GestureRecognizers>

I have two questions:
  • When the user performs the command I want to close the swipe using ResetSwipe, however I have no access to the listview in the ViewModel. How can I achieve this?
  • I want to conditionally disable/enable the swipe based on a property of the listview item. How can I do this in the MVVM and the ViewModel?
Thanks in advance.

3 Replies 1 reply marked as answer

LN Lakshmi Natarajan Syncfusion Team October 27, 2020 10:04 AM UTC

Hi Ian, 
 
Thank you for using Syncfusion products. 
 
We have checked the reported queries from our end. 
 
#Regarding I want to conditionally disable/enable the swipe based on a property of the listview item 
 
We would like to inform you that you can conditionally swipe the ListViewItem by cancelling the swipe in the SwipeStarted event. Please refer the following documentation regarding the same, 
 
To achieve your requirement in MVVM, you can use EventToCommand behavior for SfListView. Please refer our user guidance document regarding the same from the following link, 
 
Please refer the code snippets, 
XAML: Bind SwipeStarted command using EventToCommand behavior 
            <syncfusion:SfListView x:Name="listView" ItemSpacing="1" AllowSwiping="True" AutoFitMode="Height" SelectionMode="None" ItemsSource="{Binding contactsinfo}"> 
                <syncfusion:SfListView.Behaviors> 
                    <local:EventToCommandBehavior EventName="SwipeStarted" Command="{Binding SwipeStartedCommand}"/> 
                </syncfusion:SfListView.Behaviors> 
                <syncfusion:SfListView.ItemTemplate > 
                    <DataTemplate> 
                        <Grid x:Name="grid" BackgroundColor="{Binding BackgroundColor}"> 
                            ... 
                            </Grid> 
                        </Grid> 
                    </DataTemplate> 
                </syncfusion:SfListView.ItemTemplate> 
... 
            </syncfusion:SfListView> 
 
ViewModel: You can get the SwipeStartedEventArgs from the command parameter and cancel the swiping using Cancel property based on the condition. 
public class ContactsViewModel : INotifyPropertyChanged 
{ 
    public ObservableCollection<Contacts> contactsinfo { get; set; } 
    public Command<object> SwipeStartedCommand { get; set; } 
    private SfListView SfListView; 
 
    public ContactsViewModel() 
    { 
        contactsinfo = new ObservableCollection<Contacts>(); 
        SwipeStartedCommand = new Command<object>(OnSwipeStarted); 
        GenerateInfo(); 
    } 
 
    private void OnSwipeStarted(object obj) 
    { 
        var args = obj as Syncfusion.ListView.XForms.SwipeStartedEventArgs; 
        if ((args.ItemData as Contacts).BackgroundColor == Color.LightGray) 
        { 
            args.Cancel = true; 
        } 
    } 
} 
 
#Regarding When the user performs the command I want to close the swipe using ResetSwipe 
 
We would like to inform you that you can achieve your requirement by using the following code snippets, 
 
XAML: Bind SwipeEnded command for SfListView and send listView instance as CommandParameter. This inturn breaks the MVVM in the other hand.  
<syncfusion:SfListView x:Name="listView" ItemSpacing="1" AllowSwiping="True" AutoFitMode="Height" SelectionMode="None" ItemsSource="{Binding contactsinfo}"> 
    <syncfusion:SfListView.Behaviors> 
        <local:EventToCommandBehavior EventName="SwipeEnded" Command="{Binding SwipeEndedCommand}" CommandParameter="{x:Reference listView}"/> 
    </syncfusion:SfListView.Behaviors> 
    <syncfusion:SfListView.ItemTemplate > 
        <DataTemplate> 
            ... 
        </DataTemplate> 
    </syncfusion:SfListView.ItemTemplate> 
     
    <syncfusion:SfListView.RightSwipeTemplate> 
        <DataTemplate> 
            <Grid BackgroundColor="Black"> 
                <Label Text="Right Swipe" TextColor="White" FontAttributes="Bold" VerticalTextAlignment="Center" HorizontalTextAlignment="Center"/> 
                <Grid.GestureRecognizers> 
                    <TapGestureRecognizer Command="{Binding Source={RelativeSource AncestorType={x:Type local:ContactsViewModel}}, Path=TakePhotoCommand}" CommandParameter="{Binding .}" /> 
                </Grid.GestureRecognizers> 
            </Grid> 
        </DataTemplate> 
    </syncfusion:SfListView.RightSwipeTemplate> 
</syncfusion:SfListView> 
 
ViewModel: In the SwipeEnded command method, get the ListView from the CommandParameter and set it to the ViewModel property. And, reset the swipe in the TakePhotoCommand method. 
public class ContactsViewModel : INotifyPropertyChanged 
{ 
    public ObservableCollection<Contacts> contactsinfo { get; set; } 
    public Command<object> SwipeEndedCommand { get; set; } 
    public Command<object> TakePhotoCommand { get; set; } 
    private SfListView SfListView; 
 
    public ContactsViewModel() 
    { 
        contactsinfo = new ObservableCollection<Contacts>(); 
        SwipeEndedCommand = new Command<object>(OnSwipeEnded); 
        TakePhotoCommand = new Command<object>(OnTakePhotoClicked); 
        GenerateInfo(); 
    } 
 
    private void OnSwipeEnded(object obj) 
    { 
        SfListView = obj as SfListView; 
    } 
 
    private void OnTakePhotoClicked(object obj) 
    { 
        SfListView.ResetSwipe(); 
    } 
} 
 
We have prepared a sample for both of your requirements and attached in the following link, 
 
Please let us know if you need further assistance. 
 
Regards, 
Lakshmi Natarajan 


Marked as answer

IA Ian October 27, 2020 10:13 PM UTC

Hi Lakshmi,

Thanks very much for your help.

I've implemented your suggestions and all is working as required. It would be better if I didn't have a reference to the listview in the datamodel though. Perhaps a listview property could be added in the future to autoclose the swipe?

I've not experienced such fantastic support for many years. I'll certainly recommend Syncfusion.

Regards,
Ian


LN Lakshmi Natarajan Syncfusion Team October 28, 2020 06:51 AM UTC

Hi Ian, 
 
Sorry for the inconvenience caused. 
 
You can get the swiped item data from the SwipeStartedEventArgs and maintain the data in the ViewModel instead of SfListView. And pass the listview instance to the CommandParameter. Please refer the following code snippets for more reference, 
 
XAML 
<syncfusion:SfListView x:Name="listView" ItemSpacing="1" AllowSwiping="True" AutoFitMode="Height" SelectionMode="None" ItemsSource="{Binding contactsinfo}"> 
    <syncfusion:SfListView.Behaviors> 
        <local:EventToCommandBehavior EventName="SwipeStarted" Command="{Binding SwipeStartedCommand}"/> 
    </syncfusion:SfListView.Behaviors> 
    <syncfusion:SfListView.RightSwipeTemplate> 
        <DataTemplate> 
            <Grid BackgroundColor="Black"> 
                <Label Text="Right Swipe" TextColor="White" FontAttributes="Bold" VerticalTextAlignment="Center" HorizontalTextAlignment="Center"/> 
                <Grid.GestureRecognizers> 
                    <TapGestureRecognizer Command="{Binding Source={RelativeSource AncestorType={x:Type local:ContactsViewModel}}, Path=TakePhotoCommand}" CommandParameter="{x:Reference listView}"/> 
                </Grid.GestureRecognizers> 
            </Grid> 
        </DataTemplate> 
    </syncfusion:SfListView.RightSwipeTemplate> 
</syncfusion:SfListView> 
 
ViewModel 
 
using Syncfusion.ListView.XForms; 
using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using Xamarin.Forms; 
 
namespace ListViewXamarin 
{ 
    public class ContactsViewModel : INotifyPropertyChanged 
    { 
        public ObservableCollection<Contacts> contactsinfo { get; set; } 
        public Command<object> SwipeStartedCommand { get; set; } 
        public Command<object> TakePhotoCommand { get; set; } 
        private Contacts SwipedItem; 
 
        public ContactsViewModel() 
        { 
            contactsinfo = new ObservableCollection<Contacts>(); 
            SwipeStartedCommand = new Command<object>(OnSwipeStarted); 
            TakePhotoCommand = new Command<object>(OnTakePhotoClicked); 
            GenerateInfo(); 
        } 
 
        private void OnTakePhotoClicked(object obj) 
        { 
            //Get the swiped item data from the SwipedItem property. 
            (obj as SfListView).ResetSwipe(); // Reset swipe 
        } 
 
        private void OnSwipeStarted(object obj) 
        { 
            var args = obj as Syncfusion.ListView.XForms.SwipeStartedEventArgs; 
            this.SwipedItem = args.ItemData as Contacts; 
            if (SwipedItem.BackgroundColor == Color.LightGray) 
            { 
                args.Cancel = true; 
            } 
        } 
    } 
} 
 
 
Please let us know if you need further assistance. 
 
Lakshmi Natarajan 
 


Loader.
Up arrow icon