Hello Team,
I am pretty exited to see the new telerik control from you. This was long anticipated.
However, I was a little disappointed to see that the Forms edition of the ListView does not have Drag & Drop reorder support.
I understand X.Forms is also in its infancy & its difficult to come up with features that support all 3 platforms in the same way.
At the same time, I was also very happy to see that ListView for Xamarin Android & iOS do support Drag & Drop for reorder.
My question is, is there a way I can write a Custom ListView Renderer of sort on xamarin Forms, that will then allow me to convert the Telerik Forms ListView to Telerik iOS or Android List view so I can support drag & drop of items?
Is there a way we can do it? Can you share any examples or at least guide us in right direction?
Thanks
ST
13 Answers, 1 is accepted
Here is how to create custom renderers for RadListView. Let's start with iOS:
- Create a class, which inherits from Telerik.XamarinForms.DataControlsRenderer.iOS.ListViewRenderer
- Override OnElementChanged method. In this method, after calling the base method, this.Control will hold a reference to the native control, so you can set its AllowCellReorder to true.
public class MyListViewRenderer : Telerik.XamarinForms.DataControlsRenderer.iOS.ListViewRenderer
{
protected override void OnElementChanged(Xamarin.Forms.Platform.iOS.ElementChangedEventArgs<
Telerik.XamarinForms.DataControls.RadListView
> e)
{
base.OnElementChanged(e);
// e.NewElement is Telerik.XamarinForms.DataControls.RadListView
// e.Control is Telerik.XamarinForms.DataControlsRenderer.iOS.TKExtendedListView, which inherits TelerikUI.TKListView i.e. this is the native control
(this.Control as TelerikUI.TKListView).AllowsCellReorder = true;
}
}
- Do not forget to register the renderer:
[assembly:ExportRenderer(typeof(Telerik.XamarinForms.DataControls.RadListView), typeof(App12.iOS.MyListViewRenderer))]
For Android, the process is quite similar:
- Create a class which inherits from Telerik.XamarinForms.DataControlsRenderer.Android.ListViewRenderer
- Override OnElementChanged method. In this method, after calling the base method, this.Control will hold a reference to a wrapper, that in turn holds the native control. In Android, you need to add ItemReorderBehavior:
public class MyListViewRenderer : Telerik.XamarinForms.DataControlsRenderer.Android.ListViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<
Telerik.XamarinForms.DataControls.RadListView
> e)
{
base.OnElementChanged(e);
// this.Control holds a reference to Telerik.XamarinForms.DataControlsRenderer.Android.ListView.RadListViewWrapper, which in turn holds
// the native com.Telerik.Widget.List.RadListView
(this.Control as RadListViewWrapper).ListView.AddBehavior(new ItemReorderBehavior());
}
}
- Finally, register the renderer:
[assembly: Xamarin.Forms.ExportRenderer(typeof(Telerik.XamarinForms.DataControls.RadListView), typeof(App12.Droid.MyListViewRenderer))]
Best regards,
Ves
Telerik

This example was very useful. I created a DragableListView that extended RadListView
using System;
using Telerik.XamarinForms.DataControls;
namespace SDKBrowser
{
public class DraggableListView :RadListView
{
}
}
Then I modified FirstLook.xaml to use the above: and voila list view reordering works beautifully!!
Keep up the good work Telerik !!
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="SDKBrowser.Examples.ListView.FirstLook"
xmlns:telerikDataControls="clr-namespace:SDKBrowser;assembly=SDKBrowser"
xmlns:telerikListView="clr-namespace:SDKBrowser.DraggableListView;assembly=SDKBrowser">
<Grid>
<telerikDataControls:DraggableListView ItemsSource="{Binding Items}"/>
</Grid>
</ContentPage>

Hi
Is there a working sample? I tried to implemented it as mentioned in the previous posts.
On iOS I see the handles and can move the rows, but as soon as I drop them, I get an ThrowKeyNotFoundException.
Not sure what I'm missing.
On android I guess I will need another layout - the current one does not show anything.
Thanks,
Thorsten
Item reordering is builtin feature of the RadListView component. You can enable it by setting the IsItemsReorderEnabled property to True.
Regards,
Pavel R. Pavlov
Telerik

Hello Pavel,
thank you for your reply.
This led me to test the issue in a separate project without other additional components.
Step one was as simple as possible. Just a Xamarin forms project with this XAML page.
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
ContentPage
xmlns
=
"http://xamarin.com/schemas/2014/forms"
xmlns:test
=
"clr-namespace:ReorderTest.Controls;assembly=ReorderTest"
x:Class
=
"ReorderTest.MainPage"
>
<
test:DraggableListView
x:Name
=
"LV"
/>
</
ContentPage
>
This was working without issues on iOS and Android.
I then tried to use a view Model and bind it to the XAML.
<
test:DraggableListView
x:Name
=
"LV"
ItemsSource
=
"{Binding List}"
/>
Result: Working without problems on Android, but throwing the exception on iOS when doing the reorder.
"The given key was not present in the dictionary."
Here is the full stack trace:
at System.ThrowHelper.ThrowKeyNotFoundException () [0x00000] in /Users/builder/data/lanes/2689/962a0506/source/maccore/_build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/external/referencesource/mscorlib/system/throwhelper.cs:70
at System.Collections.Generic.Dictionary`2[TKey,TValue].get_Item (System.Collections.Generic.TKey key) [0x00021] in /Users/builder/data/lanes/2689/962a0506/source/maccore/_build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/external/referencesource/mscorlib/system/collections/generic/dictionary.cs:176
at Telerik.XamarinForms.Common.XamarinToNativeControlExtensions.UpdateCollection[T,K] (Telerik.XamarinForms.Common.T nativeElement, Telerik.XamarinForms.Common.K xfЕlement, System.String propertyName, System.Collections.Specialized.NotifyCollectionChangedEventArgs args) [0x00024] in <filename unknown>:0
at Telerik.XamarinForms.DataControlsRenderer.iOS.ListViewRenderer.ItemsSourceCollectionChanged (System.Object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x0000c] in <filename unknown>:0
at Telerik.XamarinForms.DataControls.RadListView.RaiseItemsSourceCollectionChanged (System.Object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x0000a] in <filename unknown>:0
at System.Collections.ObjectModel.ObservableCollection`1[T].OnCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x00012] in /Users/builder/data/lanes/2689/962a0506/source/maccore/_build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/external/referencesource/System/compmod/system/collections/objectmodel/observablecollection.cs:286
at System.Collections.ObjectModel.ObservableCollection`1[T].OnCollectionChanged (NotifyCollectionChangedAction action, System.Object item, Int32 index) [0x00000] in /Users/builder/data/lanes/2689/962a0506/source/maccore/_build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/external/referencesource/System/compmod/system/collections/objectmodel/observablecollection.cs:349
at System.Collections.ObjectModel.ObservableCollection`1[T].RemoveItem (Int32 index) [0x0002b] in /Users/builder/data/lanes/2689/962a0506/source/maccore/_build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/external/referencesource/System/compmod/system/collections/objectmodel/observablecollection.cs:203
at System.Collections.ObjectModel.Collection`1[T].Remove (System.Collections.ObjectModel.T item) [0x0002d] in /Users/builder/data/lanes/2689/962a0506/source/maccore/_build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/external/referencesource/mscorlib/system/collections/objectmodel/collection.cs:134
at System.Collections.ObjectModel.Collection`1[T].System.Collections.IList.Remove (System.Object value) [0x00022] in /Users/builder/data/lanes/2689/962a0506/source/maccore/_build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/external/referencesource/mscorlib/system/collections/objectmodel/collection.cs:350
at Telerik.XamarinForms.DataControlsRenderer.iOS.ListView.ListViewDelegate.DidReorderItemFromIndexPath (TelerikUI.TKListView listView, Foundation.NSIndexPath originalIndexPath, Foundation.NSIndexPath targetIndexPath) [0x00044] in <filename unknown>:0
at (wrapper managed-to-native) UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
at UIKit.UIApplication.Main (System.String[] args, IntPtr principal, IntPtr delegate) [0x00005] in /Users/builder/data/lanes/2689/962a0506/source/maccore/src/UIKit/UIApplication.cs:77
at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00038] in /Users/builder/data/lanes/2689/962a0506/source/maccore/src/UIKit/UIApplication.cs:61
at ReorderTest.iOS.Application.Main (System.String[] args) [0x00008] in /Users/XXX/ReorderTest/ReorderTest/ReorderTest.iOS/Main.cs:17
Regards,
Thorsten
The reported issue is already fixed in our latest official version. Please download the new binaries and give it a try one more time.
Do not hesitate to contact us again if you need any further assistance.
Regards,
Pavel R. Pavlov
Telerik

Hi Pavel
I'm using version 2016.1.113 (January 13th, 2016)
As far as I can see, this is the most recent version, but the error occurs on iOS.
Kind regards,
Thorsten
Last Thursday we released an update. The latest version is 2016.1.0204. Please check it out and let us know how it goes.
Regards,
Pavel R. Pavlov
Telerik

Hi
Unfortunately it is not working. I opened a support ticket with a sample.
Regards,
Thorsten

Hi,
From IOS Renderer how to get the reordered items. Any Event or listener which get triggered when the Reorder completes?
The current version of the reorder API does not expose such event. This is why you cannot be notified when end users finish reordering out of the box. There is a way to achieve your requirement but it is related with creating custom renderer (one per platform, total two) and custom behavior or overriding specific methods. Here is what you can try to implement.
For Android project:
You will need to create a custom renderer. This is a class deriving from ListViewRenderer. In that class you can override the CreateReorderBehavior() method. In that method you should return another custom class. The second custom class should derive from ItemReorderBehavior. Inside it you will be able to override the EndReorder() method. This method will notify you when item has been reordered.
For iOS project:
You will also need to create a custom renderer (class deriving from ListViewRenderer). In that renderer you will be able to override the CreateListViewDelegateOverride() method. Inside that method you will need to return another custom class deriving from ListViewDelegate. In that customized class you will be able to override the DidReorderItemFromIndexPath() method.
I hope this will get you started.
Regards,
Pavel R. Pavlov
Telerik

What I want is, the UI must be exactly same on each platform, thus custom renderering has to be done for each control. so will telerik be useful? Please reply.
Thankyou in advance.
If yes, can you please share some links from where I can get some content to read.
You can create custom renderers for all controls within the Telerik UI for Xamarin Suite in order to access the native control and platform specific APIs. However, we cannot guarantee that identical look can be achieved due to the platforms' specifications. If you need to work with the native controls, I suggest you review the Native Controls Wrappers section. It provides information for the native controls in iOS and Android and the approach for creating renderers is identical to the one my colleague has provided in the first answer.
Have a great week.
Regards,
Stefan Nenchev
Telerik