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);
    }
}