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