This is a migrated thread and some comments may be shown as answers.

MVVM friendly

10 Answers 397 Views
ListView
This is a migrated thread and some comments may be shown as answers.
N Mackay
Top achievements
Rank 1
N Mackay asked on 17 Feb 2016, 10:18 AM

Hi,

 

Any chance you'd consider makign teh grid more MVVM friendly.

 

In ever page I have to do something like this in the code behind, I'm designing a page just now with multiple tabs and 3 Listviews (at least) so you can imagine code behind mess! I don't mind code behind for features like grouping/filters etc.

private void ListviewOrder_OnItemTapped(object sender, ItemTapEventArgs e)
       {
           ((OrderViewModel)BindingContext).SelectCommand.Execute(e.Item as OrderItem);
       }
 

It would be nice if you could attach a tap gesture to the itemtemplate with the ability to execute a command. I was told RadListView doesn't play nice with Xamarin Forms Behaviours so I stopped using that but every time I see code like this it feels like the MVVM pattern isn't been applied correctly. I know the Listview doesn't do this either but it works okay with Xamarin Forms Behaviours pluggin, at the very least it would be nice if you could make the list compatible with that pluggin.

Also swipe to execute command would be really cool too.I got it working on Android but in iOS it never registered the swipe as been complete so I give up on that.

Curious to know the team's thoughts. 

Thanks,

Norman.

 

10 Answers, 1 is accepted

Sort by
0
Rosy Topchiyska
Telerik team
answered on 19 Feb 2016, 01:46 PM
Hi Norman,

Thank you for contacting us.

We have no immediate plans to add commands to the RadListView control, but I have logged this request in our ideas and feedback portal and depending on the demand, we could include them in our future planning.

Actually, the Xamarin Forms behaviors could work fine in a scenario where you use the events provided by the RadListView control. I have attached a sample application that demonstrates this. Please, take a look and see if this could work for you. The ItemSwipeCompleted event is triggered as expected in the attached project. Please, let us know if you have any problems with it.

I hope this helps.

Regards,
Rosy Topchiyska
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
N Mackay
Top achievements
Rank 1
answered on 22 Feb 2016, 03:38 PM

Hi Rosy,

I was actually referring to the Xamarin.Forms.Behaviours pluggin which we use elsewhere to fire commands from events (onComplete for entry etc), it's useful because you don't have to define code behind for mundane stuff. I noticed a new version has been released.

https://www.nuget.org/packages/Corcav.Behaviors/

Usually I would use this XAML code, it does work with RadListView but in a support ticket I was asked not to use it.

<ListView Grid.Row="1"
              ItemsSource="{Binding Orders}"
              VerticalOptions="Fill"
              x:Name="ListviewOrder">
      <ListView.ItemTemplate>
        <DataTemplate>
          <ImageCell
              ImageSource="MyImage"
              Text="{Binding OrderName}"
              Detail="{Binding OrderNo}">
            <b:Interaction.Behaviors>
              <b:BehaviorCollection>
                <b:EventToCommand CommandNameContext="{b:RelativeContext Details}"
                                  EventName="Tapped"
                                  CommandName="SelectCommand"
                                  CommandParameter="{Binding .}" />
              </b:BehaviorCollection>
            </b:Interaction.Behaviors>
          </ImageCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>

 

Thanks of the sample but it isn't really a lot different to what I'm doing at the moment. What I'd like to ascertain is if the pluggin above is safe to use with RadListView? Does ItemSwiped enabled cause any issues using this XAML pluggin approach? This approach works fine in the vanilla Listview  so RadListView should really support this way of working too. Listview selection triggering a command shouldn't have to be done in code behind.

Thanks,

Norman.

 

 

 

0
N Mackay
Top achievements
Rank 1
answered on 22 Feb 2016, 05:41 PM

Hi Rosy,

I forgot there's an issue with that pluggin and XamlC in Listview's.

This seems to do the trick fine though and is reusable for all pages in the app.

In the View

<local:CustomRadListView BackgroundColor="#d5d4d3"                                             IsItemSwipeEnabled="True"
 ItemsSource="{Binding Orders}" SelectionMode="Single">
                        <local:CustomRadListView.Behaviors>
                            <b:RadListViewSelectedItemBehavior Command="{Binding SelectCommand}" />
                        </local:CustomRadListView.Behaviors>

Behavior extension

using System;
using System.Windows.Input;
using Telerik.XamarinForms.DataControls;
using Telerik.XamarinForms.DataControls.ListView;
using Xamarin.Forms;
 
namespace MyAppName.Behaviors
{
    public class RadListViewSelectedItemBehavior : Behavior<RadListView>
    {
        public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command", typeof(ICommand), typeof(RadListViewSelectedItemBehavior), null);
 
        public ICommand Command {
            get { return (ICommand)GetValue (CommandProperty); }
            set { SetValue (CommandProperty, value); }
        }
 
        public RadListView AssociatedObject { get; private set; }
 
        protected override void OnAttachedTo(RadListView bindable)
        {
            base.OnAttachedTo (bindable);
            AssociatedObject = bindable;
            bindable.BindingContextChanged += OnBindingContextChanged;
            bindable.ItemTapped += ListViewItemTapped;
        }
 
        protected override void OnDetachingFrom(RadListView bindable)
        {
            base.OnDetachingFrom (bindable);
            bindable.BindingContextChanged -= OnBindingContextChanged;
            bindable.ItemTapped -= ListViewItemTapped;
            AssociatedObject = null;
        }
 
        void OnBindingContextChanged (object sender, EventArgs e)
        {
            OnBindingContextChanged ();
        }
 
        void ListViewItemTapped(object sender, ItemTapEventArgs e)
        {
            if (Command == null) {
                return;
            }
 
            var parameter = e.Item;
            if (Command.CanExecute (parameter)) {
                Command.Execute (parameter);
            }
        }
 
        protected override void OnBindingContextChanged ()
        {
            base.OnBindingContextChanged ();
            BindingContext = AssociatedObject.BindingContext;
        }
    }
}

I used this blog from David Britch at Xamarin as a start point

https://blog.xamarin.com/turn-events-into-commands-with-behaviors/

My only issue is that OnDetachingFrom doesn't seem to get called. Any ideas or tweaks? It would be good if you could test at your end so there's no memory leaks.

Thanks,

Norman.

 

0
Rosy Topchiyska
Telerik team
answered on 25 Feb 2016, 05:30 PM
Hello Norman,

I have tested XamlC with the Behaviors plugin for Xamarin Forms in a scenario that does not include our controls. I had a single Button on the page and noticed that when the CommandName property is used, an exception is thrown (System.ArgumentException: serviceProvider does not provide an IRootObjectProvider). If you have different issues that are reproduced only with the RadListView control, please share with us.

I have looked through our previous communication and the reported issues with item swiping and tapping have been already resolved. The RadListView events ItemTapped and ItemSwipeCompleted are reliable and work well with the behaviors plugin. We have found an issue with ListViewTemplateCell.Tapped event not firing on Android and I will investigate it.

I have tested various scenarios and I can say that whenever the events are fired correctly, the behaviors plugin also works fine.

As for your last issue with OnDetachingFrom not being called, we have no control over this and actually this is not specific to the RadListView control. You can force calling this method by clearing the list view Behaviors collection for example in the OnDisappearing method of the page.

Let us know if you have further questions.

Regards,
Rosy Topchiyska
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
N Mackay
Top achievements
Rank 1
answered on 26 Feb 2016, 09:25 AM

Hi Rosy,

I'm got to the bottom of the issues and yes, the controls behaves correctly with regards to behaviors. Luckily I think I can use OnDisappearing now, it was a non-starter in older versions of Forms as that event triggered in iOS when your used an intent to start the email client/dial screen etc.

The only slight issues I have is that the animation to dismiss the List swipe (EndItemSwipe) doesn't look very nice in iOS, it sort of disappears and then reappears. It animates nice in Android although there is a small issue in that the 1st item in the list seems to animate when you remove an item from the collection when ItemSwipeCompleted is triggered.

I'll send a little repo project next week, it's not a big priority and overall I'm very happy with the way it works. 

Thanks for your help,

Norman.

0
Accepted
Rosy Topchiyska
Telerik team
answered on 02 Mar 2016, 09:22 AM
Hi Norman,

Thank you for the feedback. Indeed the animation on iOS doesn't look very nice and we will see what causes this behavior. The reported problem for Android seems like an issue that we already know about and we will raise its priority. I can't promise that the fix will be included in the next internal build, planned for mid-March, but it will be available for the next official release in the beginning of May.

Please, let us know if you have any other questions.

Regards,
Rosy Topchiyska
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
N Mackay
Top achievements
Rank 1
answered on 02 Mar 2016, 10:32 AM

Hi Rosy,

Thanks for that feedback, regarding MVVM, I'm now using David Britsh's pluggin for behaviors with works nicely with RadGrid.

https://www.nuget.org/packages/Behaviors.Forms/ 

<custom:CustomRadListView BackgroundColor="#ffffff" x:Name="ListviewFav"
             IsItemSwipeEnabled="True" SwipeThreshold="5" SwipeOffset="4000"
             ItemsSource="{Binding Favourites}" SelectionMode="Single">
                <telerikDataControls:RadListView.Behaviors>
                    <b:EventHandlerBehavior EventName="ItemTapped">
                        <b:InvokeCommandAction Command="{Binding SelectFavCommand}"
                          Converter="{StaticResource SelectedltemArgsToBinding}" />
                    </b:EventHandlerBehavior>
                    <b:EventHandlerBehavior EventName="ItemSwipeCompleted">
                     <b:InvokeMethodAction TargetObject="{Binding Source={x:Reference FavView}}"
                                   MethodName="OnItemSwipeCompleted" />
                    </b:EventHandlerBehavior>
                </telerikDataControls:RadListView.Behaviors>
                <telerikDataControls:RadListView.ItemTemplate>
     <DataTemplate>

You need some converters too.

using System;
using System.Globalization;
using Telerik.XamarinForms.DataControls.ListView;
using Xamarin.Forms;
 
 
namespace Foobar.Converters
{
    public class RadSelectedltemEventArgsConverter: IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var eventArgs = value as ItemTapEventArgs;
            return eventArgs != null ? eventArgs.Item : null;
        }
 
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

using System;
using System.Globalization;
using Telerik.XamarinForms.DataControls.ListView;
using Xamarin.Forms;
 
namespace Foobar.Converters
{
    public class RadSwipeCompleteltemEventArgsConverter: IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var eventArgs = value as ItemSwipeCompletedEventArgs;
            return eventArgs != null ? eventArgs.Item : null;
        }
 
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

Seems to work well, as you mention before, you just have to remember to clear the behavior collection when the page is popped.

Thought I'd post in case anyone else is looking into this.

 

 

0
Gagan
Top achievements
Rank 1
answered on 10 May 2016, 06:59 PM

http://docs.telerik.com/devtools/xamarin/controls/listview/features/listview-features-selection

The docs say theres a "SelectedItem" property. But it isn't accessible in XAML it seems.

0
Gagan
Top achievements
Rank 1
answered on 10 May 2016, 08:12 PM
N Mackay, do you mind posting a sample? I couldn't get the Item Tap command to work with behaviors. Thank you!
0
N Mackay
Top achievements
Rank 1
answered on 19 May 2016, 10:28 AM

@Gagan

Sorry for the delay in replying, I'm on annual leave.

You can do it this way:

<telerikDataControls:RadListView BackgroundColor="#ffffff" x:Name="ListviewCustomer"
                                 ItemsSource="{Binding Customers}"
                                 SelectionMode="Single">
 
              <telerikDataControls:RadListView.Behaviors>
                <b:EventHandlerBehavior EventName="ItemTapped">
                  <b:InvokeCommandAction Command="{Binding SelectCommand}"
                     Converter="{StaticResource SelectedltemArgsToBinding}" />
                </b:EventHandlerBehavior>
              </telerikDataControls:RadListView.Behaviors>

 

You have to reference the converter in your page resources

<ContentPage.Resources>
       <ResourceDictionary>
           <convert:RadSelectedltemEventArgsConverter x:Key="SelectedltemArgsToBinding" />
       </ResourceDictionary>
   </ContentPage.Resources>

You also need the value converter.

using System;
using System.Globalization;
using Telerik.XamarinForms.DataControls.ListView;
using Xamarin.Forms;
 
 
namespace Foobar.Converters
{
    public class RadSelectedltemEventArgsConverter: IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var eventArgs = value as ItemTapEventArgs;
            return eventArgs != null ? eventArgs.Item : null;
        }
 
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

The nuget package is here:

https://www.nuget.org/packages/Behaviors.Forms/

Hope that helps

Tags
ListView
Asked by
N Mackay
Top achievements
Rank 1
Answers by
Rosy Topchiyska
Telerik team
N Mackay
Top achievements
Rank 1
Gagan
Top achievements
Rank 1
Share this question
or