ListView 的自定义渲染器

自定义渲染器允许开发人员在每个平台上自定义 Xamarin.Forms 控件的外观和行为。开发人员可以使用本机控件的功能。

例如,我们需要在 ListView 中禁用滚动。在 iOS 上 ListView 是可滚动的,即使所有项目都放在屏幕上,用户也不能滚动列表。Xamarin.Forms.ListView 不管理这样的设置。在这种情况下,渲染器即将提供帮助。

首先,我们应该在 PCL 项目中创建自定义控件,它将声明一些必需的可绑定属性:

public class SuperListView : ListView
{
    public static readonly BindableProperty IsScrollingEnableProperty =
        BindableProperty.Create(nameof(IsScrollingEnable),
                                typeof(bool),
                                typeof(SuperListView),
                                true);

    public bool IsScrollingEnable
    {
        get { return (bool)GetValue(IsScrollingEnableProperty); }
        set { SetValue(IsScrollingEnableProperty, value); }
    }
}

下一步将为每个平台创建一个渲染器。

iOS 版:

[assembly: ExportRenderer(typeof(SuperListView), typeof(SuperListViewRenderer))]
namespace SuperForms.iOS.Renderers
{
    public class SuperListViewRenderer : ListViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
        {
            base.OnElementChanged(e);

            var superListView = Element as SuperListView;
            if (superListView == null)
                return;

            Control.ScrollEnabled = superListView.IsScrollingEnable;
        }
    }
}

Android(Android 的列表没有滚动,如果所有项目都放在屏幕上,所以我们不会禁用滚动,但我们仍然可以使用本机属性):

[assembly: ExportRenderer(typeof(SuperListView), typeof(SuperListViewRenderer))]
namespace SuperForms.Droid.Renderers
{
    public class SuperListViewRenderer : ListViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e)
        {
            base.OnElementChanged(e);

            var superListView = Element as SuperListView;
            if (superListView == null)
                return;
        }
    }
}

渲染器的 Element 属性是来自 PCL 项目的我的 SuperListView 控件。

渲染器的 Control 属性是本机控制。适用于 Android 的 Android.Widget.ListView 和适用于 iOS 的 UIKit.UITableView

我们将如何在 XAML 中使用它:

<ContentPage x:Name="Page"
         xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:controls="clr-namespace:SuperForms.Controls;assembly=SuperForms.Controls"
         x:Class="SuperForms.Samples.SuperListViewPage">

  <controls:SuperListView ItemsSource="{Binding Items, Source={x:Reference Page}}"
                          IsScrollingEnable="false"
                          Margin="20">
    <controls:SuperListView.ItemTemplate>
      <DataTemplate>
        <ViewCell>
          <Label Text="{Binding .}"/>
        </ViewCell>
      </DataTemplate>
    </controls:SuperListView.ItemTemplate>
  </controls:SuperListView>
</ContentPage>

.cs 的页面文件:

public partial class SuperListViewPage : ContentPage
{
    private ObservableCollection<string> _items;

    public ObservableCollection<string> Items
    {
        get { return _items; }
        set
        {
            _items = value;
            OnPropertyChanged();
        }
    }

    public SuperListViewPage()
    {
        var list = new SuperListView();

        InitializeComponent();

        var items = new List<string>(10);
        for (int i = 1; i <= 10; i++)
        {
            items.Add($"Item {i}");
        }

        Items = new ObservableCollection<string>(items);
    }
}