Set MaxRemainingItems with Command for ListView

0 Answers 99 Views
ListView ListView - Xamarin.Android ListView - Xamarin.iOS
Marco
Top achievements
Rank 1
Marco asked on 02 May 2022, 09:15 AM

Hello,

I have an issue regarding the Load on Demand behavior of the Telerik ListView for Xamarin. First i will explain how i defined my ListView and how it should work. The ListView was defined as follows:

            <telerikDataControls:RadListView
                ItemsSource="{Binding MyTickets}"
                SelectedItem="{Binding SelectedTicket, Mode=TwoWay}"
                SelectionMode="Single"
                HeaderTemplate="{StaticResource HeaderTemplate}" 
                FooterTemplate="{StaticResource FooterTemplate}"
                Grid.Row="3"
                IsLoadOnDemandEnabled="True"
                LoadOnDemandMode="Automatic">
                <telerikDataControls:RadListView.Behaviors>
                    <prism:EventToCommandBehavior
                        Command="{Binding ItemTappedCommand}"
                        EventName="ItemTapped" />
                    </telerikDataControls:RadListView.Behaviors>
                <telerikDataControls:RadListView.Commands>
                    <telerikListViewCommands:ListViewUserCommand 
                        Id="LoadOnDemand"                         
                        Command="{Binding LoadItemsCommand}" />
                </telerikDataControls:RadListView.Commands>
                <telerikDataControls:RadListView.ItemTemplate>
                                        ...
                 </telerikDataControls:RadListView.ItemTemplate>
             </telerikDataControls:RadListView>

I have left out the ItemTemplate since it is not relevant for the problem.

As you can see we use the LoadOnDemandMode Automatic for this ListView to load the Data. When the LoadOnDemand event is triggered we load the data with the LoadItemsCommand. The LoadItemsCommand loads 10 elements at a time which functions as lazy loading. The Telerik ListView default value for the MaxRemainingItems is 10. The problem now is that the LoadItemsCommand is triggered twice when opening the page since only 10 elements are loaded each time. We would like to only load 10 elements each time and if the user scrolls down we want to load the next 10 elements.

To solve this problem we tried creating a custom renderer for the ListView and change the value of MaxRemainingItems. We were able to change the value of MaxRemainingItems in the custom renderer but after doing so our LoadItemsCommand was never triggered when the user was scrolling through the ListView. The custom renderer and Listview were tested for Android. I hope you can help us resolve this issue.

We are using Telerik.UI.for.Xamarin Nuget-Package Version 2022.1.1.

Thank you in advance.

 

 

 

 

Didi
Telerik team
commented on 05 May 2022, 07:06 AM

Hi Marco,

I will need more details on the setup you have.
Regarding this sentence: When the LoadOnDemand event is triggered we load the data with the LoadItemsCommand. Are you using both the event and the command? If this is so, please avoid this practice and use only one of the approaches to load data on demand in the ListView control - the event, or the collection, or the command. 

If you can send us a sample project with the exact implementation you have, that could be of great help.

Marco
Top achievements
Rank 1
commented on 29 Aug 2022, 08:53 AM

Hello Didi,

sorry for replying so late but this issue was pushed back for us.

I tried to adapt my implementation after your comment and resulted in the following view:

View:

vTelerikListView is our custom control of your listview. I only included the relevant parts of the view.

<controls:vStackLayout>
        <telerik:vTelerikListView x:Name="listView"
                             ItemsSource="{Binding Source}"
                             IsLoadOnDemandEnabled="True"
                             LoadOnDemandMode="Automatic"
                             LoadOnDemandBufferItemsCount="10">
            <telerik:vTelerikListView.Behaviors>
                <prism:EventToCommandBehavior
                        Command="{Binding LoadItemsCommand}"
                        EventName="LoadOnDemand" />
            </telerik:vTelerikListView.Behaviors>
        </telerik:vTelerikListView>
    </controls:vStackLayout>

Additionally I tried to create a new custom renderer for the listview to change the value of MaxRemainingItems. Here you can see my implementation of the custom renderer:

using Android.Content;
using Com.Telerik.Widget.List;
using System.ComponentModel;
using Telerik.XamarinForms.DataControlsRenderer.Android.ListView;
using v.App.Droid.Renderer;
using v.App.Styling.Controls;
using v.App.Styling.Controls.Telerik;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(vTelerikListView), typeof(vTelerikListViewRenderer))]

namespace v.App.Droid.Renderer
{
    public class vTelerikListViewRenderer : Telerik.XamarinForms.DataControlsRenderer.Android.ListViewRenderer
    {
        private vTelerikListView listView => Element as vTelerikListView;
        public vTelerikListViewRenderer(Context context) : base(context)
        {
        }

        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
            LoadOnDemandBehavior loadOnDemandBehavior = new LoadOnDemandBehavior();
            loadOnDemandBehavior.Mode = LoadOnDemandBehavior.LoadOnDemandMode.Automatic;
            loadOnDemandBehavior.MaxRemainingItems = 2;
            loadOnDemandBehavior.Enabled = true;
            (this.Control as RadListViewWrapper).ListView.ClearBehaviors();
            (this.Control as RadListViewWrapper).ListView.AddBehavior(loadOnDemandBehavior);
        }
    }
}

When opening the view now, then the listview is completely frozen. No loading or scrolling of the listview is working. I think the cause of this problem could be the line "(this.Control as RadListViewWrapper).ListView.ClearBehaviors();" in the custom renderer. Without this line the error "Java.Lang.IllegalArgumentException: 'RadListView already contains a LoadOnDemandBehavior instance'" is thrown when adding the newly created LoadOnDemandBehavior , since the default LoadOnDemandBehavior already exists.

Could you maybe take a look at the view and tell me if i understood your comment correctly? Additionally is there a way to add a new LoadOnDemandBehavior  without clearing all other behaviors of the listview?

Thank you in advance.

Didi
Telerik team
commented on 29 Aug 2022, 09:48 AM

Hi Marco,

I am not sure why you use a custom renderer for this scenario. Could you please explain the reason behind this?

Telerik Xamarin.Forms ListView has a LoadOnDemandCommand, so here Event to command behavior is not needed, also a custom renderer.  
I suggest you use a renderer for specific cases when the feature is not provided in Xamarin.Forms, as the renderer may override the logic of the control. 

Regarding the ListView frozen and scrolling issues - this may occur as the control is inside a StackLayouyt. We have a troubleshooting article about this: https://docs.telerik.com/devtools/xamarin/troubleshooting/controls-are-not-appearing 
Also inside the ListView Getting started Article we have a warning note: https://docs.telerik.com/devtools/xamarin/controls/listview/listview-getting-started#3-adding-radlistview-control 

From this exception: Java.Lang.IllegalArgumentException: 'RadListView already contains a LoadOnDemandBehavior instance'" is thrown when adding the newly created LoadOnDemandBehavior , since the default LoadOnDemandBehavior already exists. -> No, you cannot add a new instance of LoadOnDemand behavior when the old one exists. You have to clear the old behavior, then add a new one. 

Marco
Top achievements
Rank 1
commented on 30 Aug 2022, 09:50 AM

Hello Didi,

thank you for the quick response!

I want to modify the value of the MaxRemainingItems-Property of the ListView but only was able to do so with a custom renderer. Is there a way to change this property without a custom renderer? If so it would be great if you could show me how that is done.

Also, I put the ListView into a Grid which helped resolved the freezing issue, so thank you for that suggestion!

Lastly I have a question regarding the removal of the old LoadOnDemand behavior. I removed the old LoadOnDemand behavior by clearing all behaviors of the ListView. Is there a way to only remove the old LoadOnDemand behavior?

 

Didi
Telerik team
commented on 31 Aug 2022, 06:17 AM | edited

Hi Marco,

Thank you for the details. I am glad to hear the scrolling and freezing issue is solved. 

Regarding the MaxRemainingItems, yes this property is only available in the native Android ListView control, so here the renderer is the option to access this property. But if the renderer somehow affects the logic in the Xamarin.Forms LoadOnDemand implementation of the app, my suggestion is to remove the renderer. 

Regarding the add/remove a concrete behavior -> you can remove it using the RemoveBehavior method: 

 control.ListView.RemoveBehavior(loadOnDemandBehavior);

 

No answers yet. Maybe you can help?

Tags
ListView ListView - Xamarin.Android ListView - Xamarin.iOS
Asked by
Marco
Top achievements
Rank 1
Share this question
or