I'm creating a custom Xamarin.Forms control that embeds `RadListView` (2017.3.1123.0). Everything works fine on iOS but when I try to interact with the list on Android (taps, swipes) it throws an exception:
My Droid project references all the assemblies described in your documentation: Telerik.Xamarin.Android.Common, Telerik.Xamarin.Android.Data, Telerik.Xamarin.Android.Input, Telerik.Xamarin.Android.List, Telerik.Xamarin.Android.Primitives, Telerik.XamarinForms.Common, Telerik.XamarinForms.DataControls.
Here is the code of the custom control:
using System;
using System.Collections;
using System.Diagnostics;
using System.Windows.Input;
using MyMd.Mobile.Core.Mvvm.Extensions;
using MyMd.Mobile.Core.Utilities;
using Xamarin.Forms;
namespace MyMd.Mobile.Core.Controls
{
public partial class MdListView
{
private const double SwipeThreshold = 30;
public static readonly BindableProperty ItemsProperty = BindableProperty.Create(nameof(Items), typeof(IEnumerable), typeof(MdListView),
propertyChanged: ItemsChanged);
public static readonly BindableProperty IsLoadingProperty = BindableProperty.Create(nameof(IsLoading), typeof(bool), typeof(MdListView), false);
public static readonly BindableProperty ItemTappedCommandProperty = BindableProperty.Create(nameof(ItemTappedCommand), typeof(ICommand), typeof(MdListView),
propertyChanged: ItemTappedCommandChanged);
public static readonly BindableProperty DeleteCommandProperty = BindableProperty.Create(nameof(DeleteCommand), typeof(ICommand), typeof(MdListView),
propertyChanged: DeleteCommandChanged);
public static readonly BindableProperty ListItemTemplateSelectorProperty = BindableProperty.Create(nameof(ListItemTemplateSelector),
typeof(DataTemplateSelector), typeof(MdListView));
public IEnumerable Items
{
get => (IEnumerable) GetValue(ItemsProperty);
set => SetValue(ItemsProperty, value);
}
public bool IsLoading
{
get => (bool) GetValue(IsLoadingProperty);
set => SetValue(IsLoadingProperty, value);
}
public ICommand ItemTappedCommand
{
get => (ICommand) GetValue(ItemTappedCommandProperty);
set => SetValue(ItemTappedCommandProperty, value);
}
public ICommand DeleteCommand
{
get => (ICommand) GetValue(ItemTappedCommandProperty);
set => SetValue(ItemTappedCommandProperty, value);
}
public DataTemplateSelector ListItemTemplateSelector
{
get => (DataTemplateSelector) GetValue(ListItemTemplateSelectorProperty);
set => SetValue(ListItemTemplateSelectorProperty, value);
}
public string ListDescription { get; set; }
public string EmptyListText { get; set; } = Properties.Resources.EmptyList;
public Style ListStyle { get; set; }
public DataTemplate ListItemTemplate { get; set; }
public View Footer { get; set; }
private bool _isEmpty;
public bool IsEmpty
{
get => _isEmpty;
set
{
_isEmpty = value;
OnPropertyChanged(nameof(IsEmpty));
}
}
public MdListView()
{
InitializeComponent();
}
private static void ItemsChanged(BindableObject bindable, object oldItems, object newItems)
{
if (newItems == oldItems || !(newItems is IEnumerable items))
return;
var listView = (MdListView) bindable;
listView.IsEmpty = items.IsEmpty();
}
private static void ItemTappedCommandChanged(BindableObject bindable, object oldCommand, object newCommand)
{
if (!(newCommand is ICommand command))
return;
var listView = (MdListView) bindable;
listView.InternalList.ItemTapped += (sender, args) => command.Execute(args.Item);
}
private static void DeleteCommandChanged(BindableObject bindable, object oldCommand, object newCommand)
{
if (!(newCommand is ICommand command))
return;
var listView = (MdListView) bindable;
listView.InternalList.IsItemSwipeEnabled = true;
listView.InternalList.SwipeThreshold = SwipeThreshold;
listView.InternalList.SwipeOffset = new Thickness(0, 0, SwipeThreshold * 2, 0);
listView.InternalList.ItemSwipeContentTemplate = new DataTemplate(() =>
{
var container = new Grid
{
Style = listView.FindResource<Style>("MdListView.SwipeContentContainerStyle")
};
container.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
container.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(SwipeThreshold * 2, GridUnitType.Absolute)});
container.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star)});
var deleteButton = new TappableImage
{
Style = listView.FindResource<Style>("MdListView.DeleteButtonStyle"),
Source = listView.FindImageSourceResouce("Image.Delete"),
TappedCommand = command
};
container.Children.Add(deleteButton, 1, 0);
return container;
});
}
}
}
Any clues what might be wrong?
Java.Lang.NoClassDefFoundError: Failed resolution of: Lcom/telerik/widget/list/R$id; ---> Java.Lang.ClassNotFoundException: Didn't find class "com.telerik.widget.list.R$id" on path: DexPathList[[zip file "/data/app/com.example.app-1/base.apk"],nativeLibraryDirectories=[/data/app/com.example.app-1/lib/x86_64, /data/app/com.example.app-1/base.apk!/lib/x86_64, /vendor/lib64, /system/lib64]] at java.lang.ClassNotFoundException: Didn't find class "com.telerik.widget.list.R$id" on path: DexPathList[[zip file "/data/app/com.example.app-1/base.apk"],nativeLibraryDirectories=[/data/app/com.example.app-1/lib/x86_64, /data/app/com.example.app-1/base.apk!/lib/x86_64, /vendor/lib64, /system/lib64]] at at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) at at java.lang.ClassLoader.loadClass(ClassLoader.java:511) at at java.lang.ClassLoader.loadClass(ClassLoader.java:469) at at com.telerik.widget.list.RadListView.trySetHotspot(RadListView.java:663) at at com.telerik.widget.list.RadListView.notifyOnDown(RadListView.java:655) at at com.telerik.widget.list.ListViewGestureListener.onTouchEvent(ListViewGestureListener.java:61) at at com.telerik.widget.list.RadListView.onTouchEvent(RadListView.java:518) at at android.view.View.dispatchTouchEvent(View.java:9294) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2547) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2240) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.VisualElementRenderer_1.n_dispatchTouchEvent(Native Method) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.VisualElementRenderer_1.dispatchTouchEvent(VisualElementRenderer_1.java:64) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.Platform_DefaultRenderer.n_dispatchTouchEvent(Native Method) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.Platform_DefaultRenderer.dispatchTouchEvent(Platform_DefaultRenderer.java:54) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.Platform_DefaultRenderer.n_dispatchTouchEvent(Native Method) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.Platform_DefaultRenderer.dispatchTouchEvent(Platform_DefaultRenderer.java:54) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.Platform_DefaultRenderer.n_dispatchTouchEvent(Native Method) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.Platform_DefaultRenderer.dispatchTouchEvent(Platform_DefaultRenderer.java:54) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.VisualElementRenderer_1.n_dispatchTouchEvent(Native Method) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.VisualElementRenderer_1.dispatchTouchEvent(VisualElementRenderer_1.java:64) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.VisualElementRenderer_1.n_dispatchTouchEvent(Native Method) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.VisualElementRenderer_1.dispatchTouchEvent(VisualElementRenderer_1.java:64) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.PlatformRenderer.n_dispatchTouchEvent(Native Method) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.PlatformRenderer.dispatchTouchEvent(PlatformRenderer.java:55) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2403) at at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1737) at at android.app.Activity.dispatchTouchEvent(Activity.java:2765) at at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:71) at at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:71) at at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2364) at at android.view.View.dispatchPointerEvent(View.java:9514) at at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4230) at at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4096) at at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642) at at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695) at at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661) at at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3787) at at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669) at at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3844) at at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642) at at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695) at at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661) at at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669) at at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642) at at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5922) at at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5896) at at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5857) at at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6025) at at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185) at at android.os.MessageQueue.nativePollOnce(Native Method) at at android.os.MessageQueue.next(MessageQueue.java:323) at at android.os.Looper.loop(Looper.java:135) at at android.app.ActivityThread.main(ActivityThread.java:5417) at at java.lang.reflect.Method.invoke(Native Method) at at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) at Suppressed: java.lang.ClassNotFoundException: com.telerik.widget.list.R$id at at java.lang.Class.classForName(Native Method) at at java.lang.BootClassLoader.findClass(ClassLoader.java:781) at at java.lang.BootClassLoader.loadClass(ClassLoader.java:841) at at java.lang.ClassLoader.loadClass(ClassLoader.java:504) at ... 84 more at Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available --- End of inner exception stack trace --- at java.lang.NoClassDefFoundError: Failed resolution of: Lcom/telerik/widget/list/R$id; at at com.telerik.widget.list.RadListView.trySetHotspot(RadListView.java:663) at at com.telerik.widget.list.RadListView.notifyOnDown(RadListView.java:655) at at com.telerik.widget.list.ListViewGestureListener.onTouchEvent(ListViewGestureListener.java:61) at at com.telerik.widget.list.RadListView.onTouchEvent(RadListView.java:518) at at android.view.View.dispatchTouchEvent(View.java:9294) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2547) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2240) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.VisualElementRenderer_1.n_dispatchTouchEvent(Native Method) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.VisualElementRenderer_1.dispatchTouchEvent(VisualElementRenderer_1.java:64) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.Platform_DefaultRenderer.n_dispatchTouchEvent(Native Method) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.Platform_DefaultRenderer.dispatchTouchEvent(Platform_DefaultRenderer.java:54) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.Platform_DefaultRenderer.n_dispatchTouchEvent(Native Method) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.Platform_DefaultRenderer.dispatchTouchEvent(Platform_DefaultRenderer.java:54) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.Platform_DefaultRenderer.n_dispatchTouchEvent(Native Method) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.Platform_DefaultRenderer.dispatchTouchEvent(Platform_DefaultRenderer.java:54) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.VisualElementRenderer_1.n_dispatchTouchEvent(Native Method) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.VisualElementRenderer_1.dispatchTouchEvent(VisualElementRenderer_1.java:64) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.VisualElementRenderer_1.n_dispatchTouchEvent(Native Method) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.VisualElementRenderer_1.dispatchTouchEvent(VisualElementRenderer_1.java:64) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.PlatformRenderer.n_dispatchTouchEvent(Native Method) at at md5b60ffeb829f638581ab2bb9b1a7f4f3f.PlatformRenderer.dispatchTouchEvent(PlatformRenderer.java:55) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) at at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2403) at at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1737) at at android.app.Activity.dispatchTouchEvent(Activity.java:2765) at at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:71) at at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:71) at at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2364) at at android.view.View.dispatchPointerEvent(View.java:9514) at at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4230) at at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4096) at at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642) at at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695) at at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661) at at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3787) at at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669) at at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3844) at at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642) at at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695) at at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661) at at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669) at at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642) at at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5922) at at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5896) at at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5857) at at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6025) at at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185) at at android.os.MessageQueue.nativePollOnce(Native Method) at at android.os.MessageQueue.next(MessageQueue.java:323) at at android.os.Looper.loop(Looper.java:135) at at android.app.ActivityThread.main(ActivityThread.java:5417) at at java.lang.reflect.Method.invoke(Native Method) at at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) at Caused by: java.lang.ClassNotFoundException: Didn't find class "com.telerik.widget.list.R$id" on path: DexPathList[[zip file "/data/app/com.example.app-1/base.apk"],nativeLibraryDirectories=[/data/app/com.example.app-1/lib/x86_64, /data/app/com.example.app-1/base.apk!/lib/x86_64, /vendor/lib64, /system/lib64]] at at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) at at java.lang.ClassLoader.loadClass(ClassLoader.java:511) at at java.lang.ClassLoader.loadClass(ClassLoader.java:469) at ... 83 more at Suppressed: java.lang.ClassNotFoundException: com.telerik.widget.list.R$id at at java.lang.Class.classForName(Native Method) at at java.lang.BootClassLoader.findClass(ClassLoader.java:781) at at java.lang.BootClassLoader.loadClass(ClassLoader.java:841) at at java.lang.ClassLoader.loadClass(ClassLoader.java:504) at ... 84 more at Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace availableMy Droid project references all the assemblies described in your documentation: Telerik.Xamarin.Android.Common, Telerik.Xamarin.Android.Data, Telerik.Xamarin.Android.Input, Telerik.Xamarin.Android.List, Telerik.Xamarin.Android.Primitives, Telerik.XamarinForms.Common, Telerik.XamarinForms.DataControls.
Here is the code of the custom control:
<?xml version="1.0" encoding="UTF-8"?><StackLayout xmlns="http://xamarin.com/schemas/2014/forms" xmlns:dataControls="clr-namespace:Telerik.XamarinForms.DataControls;assembly=Telerik.XamarinForms.DataControls" x:Class="MyMd.Mobile.Core.Controls.MdListView" x:Name="MdListViewControl" Spacing="0" VerticalOptions="FillAndExpand"> <!-- ... --> <Label IsVisible="{Binding IsEmpty, Source={x:Reference MdListViewControl}}" Text="{Binding EmptyListText, Source={x:Reference MdListViewControl}}" Style="{StaticResource PageMessageStyle}" /> <Label IsVisible="{Binding IsEmpty, Source={x:Reference MdListViewControl}, Converter={StaticResource NegationConverter}}" Text="{Binding ListDescription, Source={x:Reference MdListViewControl}}" Style="{StaticResource PageMessageStyle}" Margin="15, 0, 15, 15" /> <StackLayout Style="{StaticResource MainContainerBaseStyle}"> <ContentView IsVisible="{Binding IsLoading, Source={x:Reference MdListViewControl}}" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"> <ActivityIndicator IsRunning="{Binding IsLoading, Source={x:Reference MdListViewControl}}" VerticalOptions="Center" HorizontalOptions="Center" /> </ContentView> <dataControls:RadListView x:Name="InternalList" ItemsSource="{Binding Items, Source={x:Reference MdListViewControl}}" Style="{Binding ListStyle, Source={x:Reference MdListViewControl}}" IsVisible="{Binding IsEmpty, Source={x:Reference MdListViewControl}, Converter={StaticResource NegationConverter}}" ItemTemplate="{Binding ListItemTemplate, Source={x:Reference MdListViewControl}}" ItemTemplateSelector="{Binding ListItemTemplateSelector, Source={x:Reference MdListViewControl}}"> </dataControls:RadListView> </StackLayout></StackLayout>001.using System;002.using System.Collections;003.using System.Diagnostics;004.using System.Windows.Input;005.using MyMd.Mobile.Core.Mvvm.Extensions;006.using MyMd.Mobile.Core.Utilities;007.using Xamarin.Forms;008. 009.namespace MyMd.Mobile.Core.Controls010.{011. public partial class MdListView012. {013. private const double SwipeThreshold = 30;014. 015. public static readonly BindableProperty ItemsProperty = BindableProperty.Create(nameof(Items), typeof(IEnumerable), typeof(MdListView),016. propertyChanged: ItemsChanged);017. 018. public static readonly BindableProperty IsLoadingProperty = BindableProperty.Create(nameof(IsLoading), typeof(bool), typeof(MdListView), false);019. 020. public static readonly BindableProperty ItemTappedCommandProperty = BindableProperty.Create(nameof(ItemTappedCommand), typeof(ICommand), typeof(MdListView),021. propertyChanged: ItemTappedCommandChanged);022. 023. public static readonly BindableProperty DeleteCommandProperty = BindableProperty.Create(nameof(DeleteCommand), typeof(ICommand), typeof(MdListView),024. propertyChanged: DeleteCommandChanged);025. 026. public static readonly BindableProperty ListItemTemplateSelectorProperty = BindableProperty.Create(nameof(ListItemTemplateSelector),027. typeof(DataTemplateSelector), typeof(MdListView));028. 029. public IEnumerable Items030. {031. get => (IEnumerable) GetValue(ItemsProperty);032. set => SetValue(ItemsProperty, value);033. }034. 035. public bool IsLoading036. {037. get => (bool) GetValue(IsLoadingProperty);038. set => SetValue(IsLoadingProperty, value);039. }040. 041. public ICommand ItemTappedCommand042. {043. get => (ICommand) GetValue(ItemTappedCommandProperty);044. set => SetValue(ItemTappedCommandProperty, value);045. }046. 047. public ICommand DeleteCommand048. {049. get => (ICommand) GetValue(ItemTappedCommandProperty);050. set => SetValue(ItemTappedCommandProperty, value);051. }052. 053. public DataTemplateSelector ListItemTemplateSelector054. {055. get => (DataTemplateSelector) GetValue(ListItemTemplateSelectorProperty);056. set => SetValue(ListItemTemplateSelectorProperty, value);057. }058. 059. public string ListDescription { get; set; }060. public string EmptyListText { get; set; } = Properties.Resources.EmptyList;061. public Style ListStyle { get; set; }062. public DataTemplate ListItemTemplate { get; set; }063. public View Footer { get; set; }064. 065. private bool _isEmpty;066. public bool IsEmpty067. {068. get => _isEmpty;069. set070. {071. _isEmpty = value;072. OnPropertyChanged(nameof(IsEmpty));073. }074. }075. 076. public MdListView()077. {078. InitializeComponent();079. }080. 081. private static void ItemsChanged(BindableObject bindable, object oldItems, object newItems)082. {083. if (newItems == oldItems || !(newItems is IEnumerable items))084. return;085. 086. var listView = (MdListView) bindable;087. 088. listView.IsEmpty = items.IsEmpty();089. }090. 091. private static void ItemTappedCommandChanged(BindableObject bindable, object oldCommand, object newCommand)092. {093. if (!(newCommand is ICommand command))094. return;095. 096. var listView = (MdListView) bindable;097. 098. listView.InternalList.ItemTapped += (sender, args) => command.Execute(args.Item);099. }100. 101. private static void DeleteCommandChanged(BindableObject bindable, object oldCommand, object newCommand)102. {103. if (!(newCommand is ICommand command))104. return;105. 106. var listView = (MdListView) bindable;107. 108. listView.InternalList.IsItemSwipeEnabled = true;109. listView.InternalList.SwipeThreshold = SwipeThreshold;110. listView.InternalList.SwipeOffset = new Thickness(0, 0, SwipeThreshold * 2, 0);111. 112. listView.InternalList.ItemSwipeContentTemplate = new DataTemplate(() =>113. {114. var container = new Grid115. {116. Style = listView.FindResource<Style>("MdListView.SwipeContentContainerStyle")117. };118. 119. container.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });120. container.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(SwipeThreshold * 2, GridUnitType.Absolute)});121. container.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star)});122. 123. var deleteButton = new TappableImage124. {125. Style = listView.FindResource<Style>("MdListView.DeleteButtonStyle"),126. Source = listView.FindImageSourceResouce("Image.Delete"),127. TappedCommand = command128. };129. 130. container.Children.Add(deleteButton, 1, 0);131. 132. return container;133. });134. }135. }136.}using System.Collections;
using System.Diagnostics;
using System.Windows.Input;
using MyMd.Mobile.Core.Mvvm.Extensions;
using MyMd.Mobile.Core.Utilities;
using Xamarin.Forms;
namespace MyMd.Mobile.Core.Controls
{
public partial class MdListView
{
private const double SwipeThreshold = 30;
public static readonly BindableProperty ItemsProperty = BindableProperty.Create(nameof(Items), typeof(IEnumerable), typeof(MdListView),
propertyChanged: ItemsChanged);
public static readonly BindableProperty IsLoadingProperty = BindableProperty.Create(nameof(IsLoading), typeof(bool), typeof(MdListView), false);
public static readonly BindableProperty ItemTappedCommandProperty = BindableProperty.Create(nameof(ItemTappedCommand), typeof(ICommand), typeof(MdListView),
propertyChanged: ItemTappedCommandChanged);
public static readonly BindableProperty DeleteCommandProperty = BindableProperty.Create(nameof(DeleteCommand), typeof(ICommand), typeof(MdListView),
propertyChanged: DeleteCommandChanged);
public static readonly BindableProperty ListItemTemplateSelectorProperty = BindableProperty.Create(nameof(ListItemTemplateSelector),
typeof(DataTemplateSelector), typeof(MdListView));
public IEnumerable Items
{
get => (IEnumerable) GetValue(ItemsProperty);
set => SetValue(ItemsProperty, value);
}
public bool IsLoading
{
get => (bool) GetValue(IsLoadingProperty);
set => SetValue(IsLoadingProperty, value);
}
public ICommand ItemTappedCommand
{
get => (ICommand) GetValue(ItemTappedCommandProperty);
set => SetValue(ItemTappedCommandProperty, value);
}
public ICommand DeleteCommand
{
get => (ICommand) GetValue(ItemTappedCommandProperty);
set => SetValue(ItemTappedCommandProperty, value);
}
public DataTemplateSelector ListItemTemplateSelector
{
get => (DataTemplateSelector) GetValue(ListItemTemplateSelectorProperty);
set => SetValue(ListItemTemplateSelectorProperty, value);
}
public string ListDescription { get; set; }
public string EmptyListText { get; set; } = Properties.Resources.EmptyList;
public Style ListStyle { get; set; }
public DataTemplate ListItemTemplate { get; set; }
public View Footer { get; set; }
private bool _isEmpty;
public bool IsEmpty
{
get => _isEmpty;
set
{
_isEmpty = value;
OnPropertyChanged(nameof(IsEmpty));
}
}
public MdListView()
{
InitializeComponent();
}
private static void ItemsChanged(BindableObject bindable, object oldItems, object newItems)
{
if (newItems == oldItems || !(newItems is IEnumerable items))
return;
var listView = (MdListView) bindable;
listView.IsEmpty = items.IsEmpty();
}
private static void ItemTappedCommandChanged(BindableObject bindable, object oldCommand, object newCommand)
{
if (!(newCommand is ICommand command))
return;
var listView = (MdListView) bindable;
listView.InternalList.ItemTapped += (sender, args) => command.Execute(args.Item);
}
private static void DeleteCommandChanged(BindableObject bindable, object oldCommand, object newCommand)
{
if (!(newCommand is ICommand command))
return;
var listView = (MdListView) bindable;
listView.InternalList.IsItemSwipeEnabled = true;
listView.InternalList.SwipeThreshold = SwipeThreshold;
listView.InternalList.SwipeOffset = new Thickness(0, 0, SwipeThreshold * 2, 0);
listView.InternalList.ItemSwipeContentTemplate = new DataTemplate(() =>
{
var container = new Grid
{
Style = listView.FindResource<Style>("MdListView.SwipeContentContainerStyle")
};
container.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
container.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(SwipeThreshold * 2, GridUnitType.Absolute)});
container.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star)});
var deleteButton = new TappableImage
{
Style = listView.FindResource<Style>("MdListView.DeleteButtonStyle"),
Source = listView.FindImageSourceResouce("Image.Delete"),
TappedCommand = command
};
container.Children.Add(deleteButton, 1, 0);
return container;
});
}
}
}
Any clues what might be wrong?
