We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

How can I write a custom renderer for SfListView ?

I am using SfListView due to grouping and other features available.However, I need to disable scrolling  the list view in Android and iOS.How do I write a custom renderer for SfListView?Please take a look at this   :   http://stackoverflow.com/questions/43372519/how-can-i-write-a-custom-renderer-for-sflistview-to-disable-scrolling

9 Replies

MK Muthu Kumaran Gnanavinayagam Syncfusion Team April 13, 2017 12:04 PM UTC

Hi, 
 
Thank you for using Syncfusion Products. 
 
In SfListView, we have property “IsScrollBarVisible” for achieve your requirement “Enable/disable the ScrollBar visibility in ListView”, no need to create renderer for this. By default, the IsScrollBarVisible property value is true. You can enable/disable the scrollbar visibility for specific platforms as like below code example.  
 
Code Example[XAML]: 
<sync:SfListView x:Name="listView" ItemsSource="{Binding BookInfo}"> 
  <sync:SfListView.IsScrollBarVisible> 
    <OnPlatform x:TypeArguments="x:Boolean"> 
      <OnPlatform.Android> 
        <OnIdiom x:TypeArguments="x:Boolean" Phone="false" Tablet="false"/> 
      </OnPlatform.Android> 
      <OnPlatform.iOS> 
        <OnIdiom x:TypeArguments="x:Boolean" Phone="false" Tablet="false"/> 
      </OnPlatform.iOS> 
      <OnPlatform.WinPhone> 
        <OnIdiom x:TypeArguments="x:Boolean" Phone="true" Tablet="true"/> 
      </OnPlatform.WinPhone> 
    </OnPlatform> 
  </sync:SfListView.IsScrollBarVisible> 
</sync:SfListView> 
 
For your reference, we have attached the sample and you can download the same from the below location.     
 
Limitation:   
·       Due to some restrictions in native ScrollView renderer in Xamarin Forms, you cannot change the IsScrollBarVisible property at runtime. It can be defined only while initializing the SfListView. 
 
Please let us know if you require further assistance.  
 
Regards, 
G.Muthu Kumaran. 
 



BG bg replied to Muthu Kumaran Gnanavinayagam April 13, 2017 12:27 PM UTC

Hi, 
 
Thank you for using Syncfusion Products. 
 
In SfListView, we have property “IsScrollBarVisible” for achieve your requirement “Enable/disable the ScrollBar visibility in ListView”, no need to create renderer for this. By default, the IsScrollBarVisible property value is true. You can enable/disable the scrollbar visibility for specific platforms as like below code example.  
 
Code Example[XAML]: 
<sync:SfListView x:Name="listView" ItemsSource="{Binding BookInfo}"> 
  <sync:SfListView.IsScrollBarVisible> 
    <OnPlatform x:TypeArguments="x:Boolean"> 
      <OnPlatform.Android> 
        <OnIdiom x:TypeArguments="x:Boolean" Phone="false" Tablet="false"/> 
      </OnPlatform.Android> 
      <OnPlatform.iOS> 
        <OnIdiom x:TypeArguments="x:Boolean" Phone="false" Tablet="false"/> 
      </OnPlatform.iOS> 
      <OnPlatform.WinPhone> 
        <OnIdiom x:TypeArguments="x:Boolean" Phone="true" Tablet="true"/> 
      </OnPlatform.WinPhone> 
    </OnPlatform> 
  </sync:SfListView.IsScrollBarVisible> 
</sync:SfListView> 
 
For your reference, we have attached the sample and you can download the same from the below location.     
 
Limitation:   
·       Due to some restrictions in native ScrollView renderer in Xamarin Forms, you cannot change the IsScrollBarVisible property at runtime. It can be defined only while initializing the SfListView. 
 
Please let us know if you require further assistance.  
 
Regards, 
G.Muthu Kumaran. 
 


Thanks for the reply.
I already have the IsScrollBarVisible set to false.
This, however, does not disable the scrolling of the list view... and the bouncing in iOS. It only hides the scroll bar.

I just wanted to extend the SfListView to define SfListViewWithNoScroll, and set the  following statements in the custom renderer: 
 
iOS:
Control.AlwaysBounceVertical = false;

Control.ScrollEnabled = false;

Android:
Control.VerticalScrollBarEnabled = false;






DB Dinesh Babu Yadav Syncfusion Team April 14, 2017 11:20 AM UTC

Hi Customer, 
  
Sorry for the inconvenience caused. 
  
SfListView is completely developed with UI Virtualization and Item recycling concept and we regret to inform you that you cannot achieve your requirement “Exporting the custom renderer for SfListView in each platforms for disabling the scrolling effect”. However, the SfListView’s ScrollView gets disabled when the ListViewItems are lesser than view and similarly enabled if the ListViewItems are greater than view. If your requirement is to disable the scrollview, we recommend you to load the items which are nearly equal to or lesser than view. 
  
For your reference, we have prepared a sample in which the items are loaded lesser than view and the ScrollView is disabled as per your requirement and you can download the sample from the below link. 
  
  
Could you please check with the above sample?. If your requirement is not met then could you please provide some specific details that why would you to like to disable the ScrollView, So, that it would help us to work towards fulfilling your inline requirement. 
  
Regards, 
Dinesh Babu Yadav 
 



DK DK April 14, 2017 01:44 PM UTC

Doing this would affect the scrolling of the ListView but interaction like selection would still work out. You can't view the items below the viewport area.

 [assembly: ExportRenderer(typeof(SfListView), typeof(CustomSfListViewRenderer))]
    namespace XamarinSfListViewDemo.Droid
    {
        public class CustomSfListViewRenderer : ViewRenderer<SfListView,Android.Views.View>
        {
            private Xamarin.Forms.ScrollView scroller;

            protected override void OnElementChanged(ElementChangedEventArgs<SfListView> e)
            {
                base.OnElementChanged(e);
                var element = e.NewElement;
                scroller = (Xamarin.Forms.ScrollView)typeof(SfListView).GetField("scrollView", BindingFlags.NonPublic)
                    .GetValue(element);
                scroller.InputTransparent = true;
            }
        }
    }

I haven't tried this code in iOS but 90% it should work. Give it a try and let me know whether it helps!



DB Dinesh Babu Yadav Syncfusion Team April 17, 2017 06:29 AM UTC

Hi Customer, 
 
Thank you for the update. 
 
We have tried your code snippet for the requirement “Disabling the scrolling effect by customizing the SfListView” in Android and iOS platform renderer project. And it throws “Null Reference” exception while reflecting the ExtendedScrollView in the OnElementChanged override method. So, we have slightly modified the code for reflecting the ExtendedScrollView as like below code snippet and hence we can able to disable the scrolling effect and also you cannot able to view the items below the viewport area as per you mentioned in both Android and iOS platform. 
 
Code Snippet[C#]: 
[assembly: ExportRenderer(typeof(SfListView), typeof(CustomSfListViewRenderer))] 
namespace ListViewSample.Droid 
{ 
    public class CustomSfListViewRenderer : ViewRenderer<SfListView, Android.Views.View> 
    { 
        private Xamarin.Forms.ScrollView scroller; 
 
        protected override void OnElementChanged(ElementChangedEventArgs<SfListView> e) 
        { 
            base.OnElementChanged(e); 
            var element = e.NewElement; 
            scroller = element.GetType().GetField("scrollView", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(element) as ExtendedScrollView; 
            scroller.InputTransparent = true; 
        } 
    } 
} 
 
For your reference, we have attached the sample and you can download it from the below link. 
 
 
Please let us know if you require further assistance. 
 
Regards, 
Dinesh Babu Yadav 
 



BG bg April 19, 2017 05:01 AM UTC

Hi,
So I created a custom control as :

namespace MyApp.CustomControls
{
    public class SfListViewWithNoScroll : SfListView
    {
    }
}

And wrote an android renderer for the same as you have provided in the sample:

[assembly: ExportRenderer(typeof(SfListViewWithNoScroll), typeof(SfListViewWithNoScrollRenderer))]
namespace MyApp.Droid.CustomRenderers
{
    public class SfListViewWithNoScrollRenderer : ViewRenderer<SfListView, Android.Views.View>
    {
        private Xamarin.Forms.ScrollView scroller;

        protected override void OnElementChanged(ElementChangedEventArgs<SfListView> e)
        {
            base.OnElementChanged(e);
            var element = e.NewElement;
            scroller = element.GetType().GetField("scrollView", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(element) as ExtendedListView;
            scroller.InputTransparent = true;
        }
    }
}

which gives me a 'null reference exception' in the highlighted line.


DK DK April 19, 2017 06:11 AM UTC

Raise of  "null reference exception" is due to the Element type which you're referencing, SfListViewWithNoScroll which doesn't have a direct element called scrollView. So Instead of this line : scroller = element.GetType().GetField("scrollView", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(element) as ExtendedListView;Use:scroller = typeof(SfListView).GetField("scrollView", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(element) as ScrollView;


BG bg replied to DK April 19, 2017 12:37 PM UTC

Raise of  "null reference exception" is due to the Element type which you're referencing, SfListViewWithNoScroll which doesn't have a direct element called scrollView. So Instead of this line : scroller = element.GetType().GetField("scrollView", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(element) as ExtendedListView;Use:scroller = typeof(SfListView).GetField("scrollView", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(element) as ScrollView;

Hi Dk.
 It worked. Thanks a lot.

I, though, have another doubt....

I have a list view as :

<listView:SfListView   
                                   ItemSize="400" GroupHeaderSize="50"
                                   ItemsSource="{Binding BindedItemsSource}"
                                   AllowGroupExpandCollapse="True"
                                   SelectionMode="None">
                <listView:SfListView.DataSource >
                    <dataSource:DataSource>
                        <dataSource:DataSource.GroupDescriptors>
                            <dataSource:GroupDescriptor PropertyName="UserId"/>
                        </dataSource:DataSource.GroupDescriptors>
                    </dataSource:DataSource>
                </listView:SfListView.DataSource>

                <listView:SfListView.GroupHeaderTemplate>
                    <DataTemplate>
                        <ViewCell>
                                <ViewCell.View>
                                   <Label Text="{Binding Value}"  HorizontalOptions="Start" Margin="10,15,0,15"  LineBreakMode="TailTruncation"/>
                                 </ViewCell.View>                     
                        </ViewCell>
                    </DataTemplate>
                </listView:SfListView.GroupHeaderTemplate>
               
              <listView:SfListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <ViewCell.View>
                         </ViewCell>
                                   ///-----------------////
                         </ViewCell.View>
                    </DataTemplate>
                </listView:SfListView.ItemTemplate>
</listView:SfListView>


The BindedItemSource is a list of MyViewModel :

     public class MyViewModel
     {
        public int UserId{ get; set; }
        public string UserName { get; set; }
        public List<ChartPts> ChartPoints{ get; set; }
     }


I am getting the data from API.
Grouping based on UserId, which are unique... I need to display the UserName as group header (which may not be )...

(Although, this does not involve grouping as such, this gives me an option of expand and collapse, and that's why I am using it.

I tried binding UserName, instead of Value to the label as well, but the headers are empty.

How can I achieve this ?

Thanks.


MK Muthu Kumaran Gnanavinayagam Syncfusion Team April 20, 2017 12:44 PM UTC

Hi, 
  
In SfListView, the bindingcontext for GroupHeader item will be GroupResult, so you can’t bind properties in model in the GroupHeaderTemplate. But you can achieve your requirement “Displaying the Model(UserName) property in GroupHeaderTemplate” with the help of IValueConverter. And the bindingcontext for the Header item will be SfListView’s BindingContext, so you cannot achieve your requirement by HeaderTemplate property. We have prepared the sample based on your requirement and you can download it from the below link.   
  
  
In the sample, we bind the Items property in the GroupResult class which contains all the items in the groups and with the help of IValueConverter, any of the model property(Example: UserName) is returned and loaded into the Label’s Text property as like below code snippet, 
 
Code Snippet[XAML]:  
<ContentPage.Resources>  
  <ResourceDictionary>  
   <local:KeyToValueConverter x:Key="KeyTovalueConverter"/>  
  </ResourceDictionary>  
</ContentPage.Resources>  
 
<listView:SfListView x:Name="listView" ItemsSource="{Binding contactsinfo}" AllowGroupExpandCollapse="True"> 
  <listView:SfListView.DataSource > 
    <dataSource:DataSource> 
      <dataSource:DataSource.GroupDescriptors> 
        <dataSource:GroupDescriptor PropertyName="UserId"/> 
      </dataSource:DataSource.GroupDescriptors> 
    </dataSource:DataSource> 
  </listView:SfListView.DataSource> 
   
  <listView:SfListView.GroupHeaderTemplate> 
    <DataTemplate> 
      <ViewCell> 
        <ViewCell.View> 
         <Label Text="{Binding Items, Converter={StaticResource KeyTovalueConverter}}" HorizontalOptions="Start" 
                Margin="0,5,0,5" LineBreakMode="TailTruncation" 
                WidthRequest="100"/> 
        </ViewCell.View> 
      </ViewCell> 
    </DataTemplate> 
  </listView:SfListView.GroupHeaderTemplate> 
</listView:SfListView>  
  
  
Code Example[C#]  
public class KeyToValueConverter : IValueConverter 
{ 
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
{ 
   var contact = (value as IEnumerable).Cast<Contacts>().First(); 
   if (contact != null) 
      return contact.ContactName; 
    else 
      return null; 
} 
  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
  { 
    throw new NotImplementedException(); 
  } 
} 
  
Please let us know if you require further assistance.  
 
Regards, 
G.Muthu Kumaran. 


Loader.
Up arrow icon