Bir ListView’i Özelleştirme
Xamarin.Forms ListView, veri koleksiyonunu dikey liste olarak görüntüleyen bir görünümdür. Bu makalede, platforma özgü liste denetimlerini ve yerel hücre düzenlerini kapsülleyen ve yerel liste denetimi performansı üzerinde daha fazla denetim sağlayan bir özel işleyicinin nasıl oluşturulacağı gösterilmektedir.
Her Xamarin.Forms görünümde, yerel denetimin bir örneğini oluşturan her platform için eşlik eden bir işleyici vardır. bir ListView
uygulama tarafından Xamarin.Forms işlendiğinde, iOS'ta ListViewRenderer
sınıfın örneği oluşturulur ve bu da yerel UITableView
bir denetimin örneğini oluşturur. Android platformunda ListViewRenderer
, sınıfı yerel ListView
bir denetim örneği oluşturur. Evrensel Windows Platformu (UWP) sınıfı ListViewRenderer
yerel ListView
bir denetim örneği oluşturur. Eşlenmeyi denetleen Xamarin.Forms işleyici ve yerel denetim sınıfları hakkında daha fazla bilgi için bkz . oluşturucu Temel Sınıfları ve Yerel Denetimler.
Aşağıdaki diyagramda denetim ile bunu uygulayan ilgili yerel denetimler arasındaki ListView
ilişki gösterilmektedir:
İşleme işlemi, her platformda bir için özel işleyici oluşturarak platforma özgü özelleştirmeler uygulamak için ListView
kullanılabilir. Bunu yapma işlemi aşağıdaki gibidir:
- Özel denetim Xamarin.Forms oluşturma.
- 'den Xamarin.Formsözel denetimi kullanma.
- Her platformda denetim için özel işleyici oluşturun .
Artık platforma özgü liste denetimlerinden ve yerel hücre düzenlerinden yararlanan bir NativeListView
işleyici uygulamak için her öğe sırayla ele alınacaktır. Bu senaryo, yeniden kullanılabilecek liste ve hücre kodu içeren mevcut bir yerel uygulamayı taşıma sırasında kullanışlıdır. Ayrıca, veri sanallaştırma gibi performansı etkileyebilecek liste denetimi özelliklerinin ayrıntılı olarak özelleştirilmesini sağlar.
Özel ListView Denetimi Oluşturma
Aşağıdaki kod örneğinde gösterildiği gibi sınıfın alt sınıfı ListView
oluşturularak özel ListView
bir denetim oluşturulabilir:
public class NativeListView : ListView
{
public static readonly BindableProperty ItemsProperty =
BindableProperty.Create ("Items", typeof(IEnumerable<DataSource>), typeof(NativeListView), new List<DataSource> ());
public IEnumerable<DataSource> Items {
get { return (IEnumerable<DataSource>)GetValue (ItemsProperty); }
set { SetValue (ItemsProperty, value); }
}
public event EventHandler<SelectedItemChangedEventArgs> ItemSelected;
public void NotifyItemSelected (object item)
{
if (ItemSelected != null) {
ItemSelected (this, new SelectedItemChangedEventArgs (item));
}
}
}
, NativeListView
.NET Standard kitaplık projesinde oluşturulur ve özel denetim için API'yi tanımlar. Bu denetim, verilerle doldurma ListView
için kullanılan ve görüntüleme amacıyla bağlanabilen bir Items
özelliği kullanıma sunar. Ayrıca platforma özgü yerel ItemSelected
liste denetiminde bir öğe seçildiğinde tetiklenecek bir olayı da kullanıma sunar. Veri bağlama hakkında daha fazla bilgi için bkz . Veri Bağlama Temelleri.
Özel Denetimi Kullanma
Özel NativeListView
denetime konumu için bir ad alanı bildirilerek ve denetimdeki ad alanı ön eki kullanılarak .NET Standart kitaplık projesindeki Xaml'de başvurulabilir. Aşağıdaki kod örneği, özel denetimin NativeListView
bir XAML sayfası tarafından nasıl tüketilebileceğini gösterir:
<ContentPage ...
xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
...>
...
<ContentPage.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Text="{x:Static local:App.Description}" HorizontalTextAlignment="Center" />
<local:NativeListView Grid.Row="1" x:Name="nativeListView" ItemSelected="OnItemSelected" VerticalOptions="FillAndExpand" />
</Grid>
</ContentPage.Content>
</ContentPage>
Ad local
alanı ön eki herhangi bir adla adlandırılabilir. Ancak ve clr-namespace
assembly
değerleri özel denetimin ayrıntılarıyla eşleşmelidir. Ad alanı bildirildikten sonra, özel denetime başvurmak için ön ek kullanılır.
Aşağıdaki kod örneği, özel denetimin NativeListView
bir C# sayfası tarafından nasıl kullanılıp kullanılamayabileceğini gösterir:
public class MainPageCS : ContentPage
{
NativeListView nativeListView;
public MainPageCS()
{
nativeListView = new NativeListView
{
Items = DataSource.GetList(),
VerticalOptions = LayoutOptions.FillAndExpand
};
switch (Device.RuntimePlatform)
{
case Device.iOS:
Padding = new Thickness(0, 20, 0, 0);
break;
case Device.Android:
case Device.UWP:
Padding = new Thickness(0);
break;
}
Content = new Grid
{
RowDefinitions = {
new RowDefinition { Height = GridLength.Auto },
new RowDefinition { Height = new GridLength (1, GridUnitType.Star) }
},
Children = {
new Label { Text = App.Description, HorizontalTextAlignment = TextAlignment.Center },
nativeListView
}
};
nativeListView.ItemSelected += OnItemSelected;
}
...
}
Özel NativeListView
denetim, özellik aracılığıyla doldurulan bir veri listesi görüntülemek için platforma Items
özgü özel işleyicileri kullanır. Listedeki her satır üç veri öğesi içerir: ad, kategori ve görüntü dosya adı. Listedeki her satırın düzeni platforma özgü özel işleyici tarafından tanımlanır.
Not
NativeListView
Özel denetim, kaydırma özelliğini içeren platforma özgü liste denetimleri kullanılarak işlenecek olduğundan, özel denetim gibi ScrollView
kaydırılabilir düzen denetimlerinde barındırılmamalıdır.
Artık platforma özgü liste denetimleri ve yerel hücre düzenleri oluşturmak için her uygulama projesine özel işleyici eklenebilir.
Her Platformda Özel oluşturucu oluşturma
Özel işleyici sınıfını oluşturma işlemi aşağıdaki gibidir:
- Özel denetimi işleyen sınıfının bir alt sınıfını
ListViewRenderer
oluşturun. OnElementChanged
Özel denetimi işleyen yöntemini geçersiz kılın ve özelleştirmek için mantık yazın. Bu yöntem, karşılık gelen Xamarin.FormsListView
oluşturulduğunda çağrılır.- Özel denetimi işlemek için kullanılacağını belirtmek için özel işleyici sınıfına Xamarin.Forms bir
ExportRenderer
öznitelik ekleyin. Bu öznitelik, özel işleyiciyi ile Xamarin.Formskaydetmek için kullanılır.
Not
Her platform projesinde özel işleyici sağlamak isteğe bağlıdır. Özel işleyici kaydedilmediyse, hücrenin temel sınıfı için varsayılan işleyici kullanılır.
Aşağıdaki diyagramda, örnek uygulamadaki her projenin sorumlulukları ve aralarındaki ilişkiler gösterilmektedir:
Özel NativeListView
denetim, her platform için sınıfından ListViewRenderer
türetilen platforma özgü işleyici sınıfları tarafından işlenir. Bu, her NativeListView
özel denetimin aşağıdaki ekran görüntülerinde gösterildiği gibi platforma özgü liste denetimleri ve yerel hücre düzenleriyle işlenmesine neden olur:
ListViewRenderer
sınıfı, ilgili yerel denetimi işlemek için özel denetim oluşturulduğunda çağrılan Xamarin.Forms yöntemini kullanıma sunarOnElementChanged
. Bu yöntem ve NewElement
özelliklerini içeren OldElement
bir ElementChangedEventArgs
parametre alır. Bu özellikler, işleyicinin eklendiği öğeyi ve Xamarin.Forms sırasıyla işleyicinin eklendiği öğeyi temsil Xamarin.Forms edilir. Örnek uygulamada özelliği OldElement
olur null
ve NewElement
özelliği örneğe bir başvuru NativeListView
içerir.
Her platforma özgü işleyici sınıfında yöntemin OnElementChanged
geçersiz kılınmış bir sürümü, yerel denetim özelleştirmesinin gerçekleştirebileceğiniz yerdir. Platformda kullanılan yerel denetime yazılan başvuruya özelliği üzerinden Control
erişilebilir. Ayrıca, işlenen denetime Xamarin.Forms bir başvuru özelliği aracılığıyla Element
elde edilebilir.
Aşağıdaki kod örneğinde gösterildiği gibi yöntemindeki OnElementChanged
olay işleyicilerine abone olurken dikkatli olunmalıdır:
protected override void OnElementChanged (ElementChangedEventArgs<Xamarin.Forms.ListView> e)
{
base.OnElementChanged (e);
if (e.OldElement != null) {
// Unsubscribe from event handlers and cleanup any resources
}
if (e.NewElement != null) {
// Configure the native control and subscribe to event handlers
}
}
Yerel denetim yalnızca özel işleyici yeni Xamarin.Forms bir öğeye eklendiğinde yapılandırılmalıdır ve olay işleyicileri abone olmalıdır. Benzer şekilde, abone olunan tüm olay işleyicilerinin aboneliği yalnızca işleyicinin değişikliklere eklendiği öğe olduğunda aboneliği kaldırılmalıdır. Bu yaklaşımı benimsemek, bellek sızıntılarından muzdarip olmayan özel bir işleyici oluşturmaya yardımcı olur.
Yöntemin OnElementPropertyChanged
geçersiz kılınmış sürümü, platforma özgü işleyici sınıflarında özel denetimdeki Xamarin.Forms bağlanabilir özellik değişikliklerine yanıt verilebilen yerdir. Bu geçersiz kılma birçok kez çağrılabildiği için, değiştirilen özellik için her zaman bir denetim yapılmalıdır.
Her özel işleyici sınıfı, işleyiciyi ile kaydeden bir ExportRenderer
öznitelikle Xamarin.Formsdekore edilmiştir. özniteliği iki parametre alır: işlenen özel denetimin Xamarin.Forms tür adı ve özel işleyicinin tür adı. assembly
özniteliğinin ön eki, özniteliğin tüm derleme için geçerli olduğunu belirtir.
Aşağıdaki bölümlerde platforma özgü özel işleyici sınıflarının uygulanması açıklanmıştır.
iOS'ta Özel oluşturucu oluşturma
Aşağıdaki kod örneği, iOS platformu için özel işleyiciyi gösterir:
[assembly: ExportRenderer (typeof(NativeListView), typeof(NativeiOSListViewRenderer))]
namespace CustomRenderer.iOS
{
public class NativeiOSListViewRenderer : ListViewRenderer
{
protected override void OnElementChanged (ElementChangedEventArgs<Xamarin.Forms.ListView> e)
{
base.OnElementChanged (e);
if (e.OldElement != null) {
// Unsubscribe
}
if (e.NewElement != null) {
Control.Source = new NativeiOSListViewSource (e.NewElement as NativeListView);
}
}
}
}
DenetimUITableView
, özel işleyicinin yeni Xamarin.Forms bir öğeye NativeiOSListViewSource
eklenmesi koşuluyla sınıfının bir örneği oluşturularak yapılandırılır. Bu sınıf, sınıfından UITableView
ve GetCell
yöntemlerini UITableViewSource
geçersiz kılarak RowsInSection
ve görüntülenecek veri listesini içeren bir Items
özelliği kullanıma sunarak denetime veri sağlar. sınıfı, özel denetim tarafından NativeListView
sağlanan olayı çağıran ItemSelected
bir RowSelected
yöntem geçersiz kılma da sağlar. Yöntem geçersiz kılmaları hakkında daha fazla bilgi için bkz . UITableViewSource Alt Sınıfı oluşturma. GetCell
yöntemi, listedeki her satır için verilerle doldurulmuş bir UITableCellView
döndürür ve aşağıdaki kod örneğinde gösterilir:
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
// request a recycled cell to save memory
NativeiOSListViewCell cell = tableView.DequeueReusableCell (cellIdentifier) as NativeiOSListViewCell;
// if there are no cells to reuse, create a new one
if (cell == null) {
cell = new NativeiOSListViewCell (cellIdentifier);
}
if (String.IsNullOrWhiteSpace (tableItems [indexPath.Row].ImageFilename)) {
cell.UpdateCell (tableItems [indexPath.Row].Name
, tableItems [indexPath.Row].Category
, null);
} else {
cell.UpdateCell (tableItems [indexPath.Row].Name
, tableItems [indexPath.Row].Category
, UIImage.FromFile ("Images/" + tableItems [indexPath.Row].ImageFilename + ".jpg"));
}
return cell;
}
Bu yöntem, ekranda görüntülenecek her veri satırı için bir NativeiOSListViewCell
örnek oluşturur. Örnek, NativeiOSCell
her hücrenin düzenini ve hücre verilerini tanımlar. Kaydırma nedeniyle bir hücre ekrandan kaybolduğunda, hücre yeniden kullanılabilir hale getirilecektir. Bu, listedeki tüm veriler yerine yalnızca NativeiOSCell
ekranda görüntülenen verilerin örneklerinin bulunduğundan emin olarak belleğin boşa harcanmasını önler. Hücre yeniden kullanımı hakkında daha fazla bilgi için bkz . Hücre Yeniden Kullanımı. Yöntemi GetCell
ayrıca, mevcut olması koşuluyla her veri satırının özelliğini okur ImageFilename
ve örneği satır için verilerle (ad, kategori ve görüntü) güncelleştirmeden NativeiOSListViewCell
önce görüntüyü okur ve örnek UIImage
olarak depolar.
NativeiOSListViewCell
sınıfı her hücrenin düzenini tanımlar ve aşağıdaki kod örneğinde gösterilir:
public class NativeiOSListViewCell : UITableViewCell
{
UILabel headingLabel, subheadingLabel;
UIImageView imageView;
public NativeiOSListViewCell (NSString cellId) : base (UITableViewCellStyle.Default, cellId)
{
SelectionStyle = UITableViewCellSelectionStyle.Gray;
ContentView.BackgroundColor = UIColor.FromRGB (218, 255, 127);
imageView = new UIImageView ();
headingLabel = new UILabel () {
Font = UIFont.FromName ("Cochin-BoldItalic", 22f),
TextColor = UIColor.FromRGB (127, 51, 0),
BackgroundColor = UIColor.Clear
};
subheadingLabel = new UILabel () {
Font = UIFont.FromName ("AmericanTypewriter", 12f),
TextColor = UIColor.FromRGB (38, 127, 0),
TextAlignment = UITextAlignment.Center,
BackgroundColor = UIColor.Clear
};
ContentView.Add (headingLabel);
ContentView.Add (subheadingLabel);
ContentView.Add (imageView);
}
public void UpdateCell (string caption, string subtitle, UIImage image)
{
headingLabel.Text = caption;
subheadingLabel.Text = subtitle;
imageView.Image = image;
}
public override void LayoutSubviews ()
{
base.LayoutSubviews ();
headingLabel.Frame = new CoreGraphics.CGRect (5, 4, ContentView.Bounds.Width - 63, 25);
subheadingLabel.Frame = new CoreGraphics.CGRect (100, 18, 100, 20);
imageView.Frame = new CoreGraphics.CGRect (ContentView.Bounds.Width - 63, 5, 33, 33);
}
}
Bu sınıf, hücrenin içeriğini ve bunların düzenini işlemek için kullanılan denetimleri tanımlar. OluşturucuNativeiOSListViewCell
, ve UIImageView
denetimlerinin UILabel
örneklerini oluşturur ve görünümlerini başlatır. Bu denetimler, ve örneklerinde bu verileri ayarlamak için kullanılan yöntemle birlikte UpdateCell
her satırın UILabel
UIImageView
verilerini görüntülemek için kullanılır. Bu örneklerin konumu geçersiz kılınan LayoutSubviews
yöntem tarafından hücre içinde koordinatları belirtilerek ayarlanır.
Özel Denetimde Özellik Değişikliğine Yanıt Verme
NativeListView.Items
Özellik değişirse, listeye eklenen veya listeden kaldırılan öğeler nedeniyle, özel işleyicinin değişiklikleri görüntüleyerek yanıt vermesi gerekir. Bu, aşağıdaki kod örneğinde gösterilen yöntemini geçersiz kılarak OnElementPropertyChanged
gerçekleştirilebilir:
protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged (sender, e);
if (e.PropertyName == NativeListView.ItemsProperty.PropertyName) {
Control.Source = new NativeiOSListViewSource (Element as NativeListView);
}
}
yöntemi, bindable NativeListView.Items
özelliğinin NativeiOSListViewSource
değiştirilmesi koşuluyla denetime UITableView
veri sağlayan sınıfının yeni bir örneğini oluşturur.
Android'de Özel oluşturucu oluşturma
Aşağıdaki kod örneği, Android platformu için özel işleyiciyi gösterir:
[assembly: ExportRenderer(typeof(NativeListView), typeof(NativeAndroidListViewRenderer))]
namespace CustomRenderer.Droid
{
public class NativeAndroidListViewRenderer : ListViewRenderer
{
Context _context;
public NativeAndroidListViewRenderer(Context context) : base(context)
{
_context = context;
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
// unsubscribe
Control.ItemClick -= OnItemClick;
}
if (e.NewElement != null)
{
// subscribe
Control.Adapter = new NativeAndroidListViewAdapter(_context as Android.App.Activity, e.NewElement as NativeListView);
Control.ItemClick += OnItemClick;
}
}
...
void OnItemClick(object sender, Android.Widget.AdapterView.ItemClickEventArgs e)
{
((NativeListView)Element).NotifyItemSelected(((NativeListView)Element).Items.ToList()[e.Position - 1]);
}
}
}
Özel işleyicinin yeni Xamarin.Forms bir öğeye bağlı olması koşuluyla yerel ListView
denetim yapılandırılır. Bu yapılandırma, yerel ListView
denetime veri sağlayan sınıfın NativeAndroidListViewAdapter
bir örneğini oluşturmayı ve olayı işlemek için bir olay işleyicisi kaydetmeyi ItemClick
içerir. Buna karşılık, bu işleyici özel denetim tarafından NativeListView
sağlanan olayı çağırırItemSelected
. İşleyicinin ItemClick
ekli olduğu öğe değişikliklere bağlıysa Xamarin.Forms olayının aboneliği kaldırılır.
NativeAndroidListViewAdapter
sınıfından BaseAdapter
türetilir ve görüntülenecek veri listesini içeren bir Items
özelliğin yanı sıra , GetView
, GetItemId
ve this[int]
yöntemlerini geçersiz kılarak Count
kullanıma sunar. Bu yöntem geçersiz kılmaları hakkında daha fazla bilgi için bkz . ListAdapter Uygulama. GetView
yöntemi, her satır için verilerle doldurulmuş bir görünüm döndürür ve aşağıdaki kod örneğinde gösterilir:
public override View GetView (int position, View convertView, ViewGroup parent)
{
var item = tableItems [position];
var view = convertView;
if (view == null) {
// no view to re-use, create new
view = context.LayoutInflater.Inflate (Resource.Layout.NativeAndroidListViewCell, null);
}
view.FindViewById<TextView> (Resource.Id.Text1).Text = item.Name;
view.FindViewById<TextView> (Resource.Id.Text2).Text = item.Category;
// grab the old image and dispose of it
if (view.FindViewById<ImageView> (Resource.Id.Image).Drawable != null) {
using (var image = view.FindViewById<ImageView> (Resource.Id.Image).Drawable as BitmapDrawable) {
if (image != null) {
if (image.Bitmap != null) {
//image.Bitmap.Recycle ();
image.Bitmap.Dispose ();
}
}
}
}
// If a new image is required, display it
if (!String.IsNullOrWhiteSpace (item.ImageFilename)) {
context.Resources.GetBitmapAsync (item.ImageFilename).ContinueWith ((t) => {
var bitmap = t.Result;
if (bitmap != null) {
view.FindViewById<ImageView> (Resource.Id.Image).SetImageBitmap (bitmap);
bitmap.Dispose ();
}
}, TaskScheduler.FromCurrentSynchronizationContext ());
} else {
// clear the image
view.FindViewById<ImageView> (Resource.Id.Image).SetImageBitmap (null);
}
return view;
}
GetView
yöntemi, listedeki her veri satırı için işlenecek hücreyi olarak View
döndürmek için çağrılır. Ekranda görüntülenecek her veri satırı için bir View
örnek oluşturur ve örneğin görünümü View
bir düzen dosyasında tanımlanır. Kaydırma nedeniyle bir hücre ekrandan kaybolduğunda, hücre yeniden kullanılabilir hale getirilecektir. Bu, listedeki tüm veriler yerine yalnızca View
ekranda görüntülenen verilerin örneklerinin bulunduğundan emin olarak belleğin boşa harcanmasını önler. Görünümü yeniden kullanma hakkında daha fazla bilgi için bkz . Satır Görünümü Yeniden Kullanımı.
GetView
yöntemi ayrıca, özelliğinde ImageFilename
belirtilen dosya adından View
görüntü verilerini okumak da dahil olmak üzere örneği verilerle doldurur.
Yerel ListView
tarafından ödenmemiş her hücrenin düzeni, yöntemi tarafından LayoutInflater.Inflate
şişirilen düzen dosyasında tanımlanırNativeAndroidListViewCell.axml
. Aşağıdaki kod örneği düzen tanımını gösterir:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:background="@drawable/CustomSelector">
<LinearLayout
android:id="@+id/Text"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dip">
<TextView
android:id="@+id/Text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FF7F3300"
android:textSize="20dip"
android:textStyle="italic" />
<TextView
android:id="@+id/Text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14dip"
android:textColor="#FF267F00"
android:paddingLeft="100dip" />
</LinearLayout>
<ImageView
android:id="@+id/Image"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="5dp"
android:src="@drawable/icon"
android:layout_alignParentRight="true" />
</RelativeLayout>
Bu düzen, hücrenin içeriğini görüntülemek için iki TextView
denetimin ve bir ImageView
denetimin kullanıldığını belirtir. İki TextView
denetim bir denetim içinde LinearLayout
dikey olarak yönlendirilir ve tüm denetimler içinde RelativeLayout
yer alır.
Özel Denetimde Özellik Değişikliğine Yanıt Verme
NativeListView.Items
Özellik değişirse, listeye eklenen veya listeden kaldırılan öğeler nedeniyle, özel işleyicinin değişiklikleri görüntüleyerek yanıt vermesi gerekir. Bu, aşağıdaki kod örneğinde gösterilen yöntemini geçersiz kılarak OnElementPropertyChanged
gerçekleştirilebilir:
protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged (sender, e);
if (e.PropertyName == NativeListView.ItemsProperty.PropertyName) {
Control.Adapter = new NativeAndroidListViewAdapter (_context as Android.App.Activity, Element as NativeListView);
}
}
yöntemi, bağlanabilir NativeListView.Items
özelliğin NativeAndroidListViewAdapter
değiştirilmesi koşuluyla yerel ListView
denetime veri sağlayan sınıfının yeni bir örneğini oluşturur.
UWP üzerinde Özel oluşturucu oluşturma
Aşağıdaki kod örneği, UWP için özel işleyiciyi gösterir:
[assembly: ExportRenderer(typeof(NativeListView), typeof(NativeUWPListViewRenderer))]
namespace CustomRenderer.UWP
{
public class NativeUWPListViewRenderer : ListViewRenderer
{
ListView listView;
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e)
{
base.OnElementChanged(e);
listView = Control as ListView;
if (e.OldElement != null)
{
// Unsubscribe
listView.SelectionChanged -= OnSelectedItemChanged;
}
if (e.NewElement != null)
{
listView.SelectionMode = ListViewSelectionMode.Single;
listView.IsItemClickEnabled = false;
listView.ItemsSource = ((NativeListView)e.NewElement).Items;
listView.ItemTemplate = App.Current.Resources["ListViewItemTemplate"] as Windows.UI.Xaml.DataTemplate;
// Subscribe
listView.SelectionChanged += OnSelectedItemChanged;
}
}
void OnSelectedItemChanged(object sender, SelectionChangedEventArgs e)
{
((NativeListView)Element).NotifyItemSelected(listView.SelectedItem);
}
}
}
Özel işleyicinin yeni Xamarin.Forms bir öğeye bağlı olması koşuluyla yerel ListView
denetim yapılandırılır. Bu yapılandırma, yerel ListView
denetimin seçilen öğelere nasıl yanıt vereceğini ayarlamayı, denetim tarafından görüntülenen verileri doldurmayı, her hücrenin görünümünü ve içeriğini tanımlamayı ve olayı işlemek için bir olay işleyicisi kaydetmeyi SelectionChanged
içerir. Buna karşılık, bu işleyici özel denetim tarafından NativeListView
sağlanan olayı çağırırItemSelected
. İşleyicinin SelectionChanged
ekli olduğu öğe değişikliklere bağlıysa Xamarin.Forms olayının aboneliği kaldırılır.
Her yerel ListView
hücrenin görünümü ve içeriği adlandırılmış ListViewItemTemplate
bir DataTemplate
tarafından tanımlanır. Bu DataTemplate
, uygulama düzeyi kaynak sözlüğünde depolanır ve aşağıdaki kod örneğinde gösterilir:
<DataTemplate x:Key="ListViewItemTemplate">
<Grid Background="#DAFF7F">
<Grid.Resources>
<local:ConcatImageExtensionConverter x:Name="ConcatImageExtensionConverter" />
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.40*" />
<ColumnDefinition Width="0.40*"/>
<ColumnDefinition Width="0.20*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.ColumnSpan="2" Foreground="#7F3300" FontStyle="Italic" FontSize="22" VerticalAlignment="Top" Text="{Binding Name}" />
<TextBlock Grid.RowSpan="2" Grid.Column="1" Foreground="#267F00" FontWeight="Bold" FontSize="12" VerticalAlignment="Bottom" Text="{Binding Category}" />
<Image Grid.RowSpan="2" Grid.Column="2" HorizontalAlignment="Left" VerticalAlignment="Center" Source="{Binding ImageFilename, Converter={StaticResource ConcatImageExtensionConverter}}" Width="50" Height="50" />
<Line Grid.Row="1" Grid.ColumnSpan="3" X1="0" X2="1" Margin="30,20,0,0" StrokeThickness="1" Stroke="LightGray" Stretch="Fill" VerticalAlignment="Bottom" />
</Grid>
</DataTemplate>
hücrenin DataTemplate
içeriğini ve bunların düzenini ve görünümünü görüntülemek için kullanılan denetimleri belirtir. Hücrenin içeriğini veri bağlama aracılığıyla görüntülemek için iki TextBlock
denetim ve bir Image
denetim kullanılır. Ayrıca, dosya uzantısını ConcatImageExtensionConverter
her resim dosya adıyla birleştirmek .jpg
için bir örneği kullanılır. Bu, denetimin Image
özelliği ayarlandığında görüntüyü Source
yükleyebilmesini ve işleyebilmesini sağlar.
Özel Denetimde Özellik Değişikliğine Yanıt Verme
NativeListView.Items
Özellik değişirse, listeye eklenen veya listeden kaldırılan öğeler nedeniyle, özel işleyicinin değişiklikleri görüntüleyerek yanıt vermesi gerekir. Bu, aşağıdaki kod örneğinde gösterilen yöntemini geçersiz kılarak OnElementPropertyChanged
gerçekleştirilebilir:
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == NativeListView.ItemsProperty.PropertyName)
{
listView.ItemsSource = ((NativeListView)Element).Items;
}
}
yöntemi, yerel denetimi, bağlanabilir NativeListView.Items
özelliğin ListView
değiştirilmesi koşuluyla değiştirilen verilerle yeniden doldurur.
Özet
Bu makalede, platforma özgü liste denetimlerini ve yerel hücre düzenlerini kapsülleyen ve yerel liste denetimi performansı üzerinde daha fazla denetim sağlayan özel işleyicinin nasıl oluşturulacağı gösterilmiştir.