5

IOS'ta bir UICollectionView'a dönüştüren Xamarin Formlarında Özel Görünüm oluşturmaya çalışıyorum.Xamarin Formlar DataTemplate ile UICollectionView

Bu ilk şey yapmak oldukça basittir:

Görünüm:

public class CollectionView : View 
{ 

} 

Renderer: Artık

public class CollectionViewRenderer : ViewRenderer<CollectionView, UICollectionView> 
{ 

    protected override void OnElementChanged(ElementChangedEventArgs<CollectionView> e) 
    { 
     base.OnElementChanged(e); 

     if (Control == null) 
     { 
      SetNativeControl(new UICollectionView(new CGRect(0, 0, 200, 200), new UICollectionViewFlowLayout())); 
     } 

     if (e.NewElement != null) 
     { 
      ... 
      Control.Source = new CollectionViewSource(a, this); 
      Control.ReloadData(); 
     } 
    } 
} 

I (a DataTemplateSelector itibaren) DataTemplates bu CollectionView'ın beslemek istiyorum . Yapabileceğiniz Şablondan'ı

: Ama sınıflar kaydetmek için bir yol bulmak mümkün değilim

Template.CreateContent(); 

UI öğesi alır.

Ama nasıl CollectionSource

ör .:

CollectionView.RegisterClassForCell(typeof(????), "CellId"); 

cevap

0

Hope dequeue'ing için CollectionView'ın bunu kayıt olabilirsiniz, bu size yardımcı olacaktır !!!

CustomControl

GridCollectionView.cs

using System; 
using CoreGraphics; 
using Foundation; 
using UIKit; 


namespace MyApp.Forms.Controls 
{ 
    public class GridCollectionView : UICollectionView 
    { 
     public GridCollectionView() : this (default(CGRect)) 
     { 
     } 


     public GridCollectionView(CGRect frm) 
      : base(frm, new UICollectionViewFlowLayout()) 
     { 
      AutoresizingMask = UIViewAutoresizing.All; 
      ContentMode = UIViewContentMode.ScaleToFill; 
      RegisterClassForCell(typeof(GridViewCell), new NSString (GridViewCell.Key)); 
     } 


     public bool SelectionEnable 
     { 
      get; 
      set; 
     } 


     public double RowSpacing 
     { 
      get 
      { 
       return ((UICollectionViewFlowLayout)this.CollectionViewLayout).MinimumLineSpacing; 
      } 
      set 
      { 
       ((UICollectionViewFlowLayout)this.CollectionViewLayout).MinimumLineSpacing = (nfloat)value; 
      } 
     } 


     public double ColumnSpacing 
     { 
      get 
      { 
       return ((UICollectionViewFlowLayout)this.CollectionViewLayout).MinimumInteritemSpacing; 
      } 
      set 
      { 
       ((UICollectionViewFlowLayout)this.CollectionViewLayout).MinimumInteritemSpacing = (nfloat)value; 
      } 
     } 


     public CGSize ItemSize 
     { 
      get 
      { 
       return ((UICollectionViewFlowLayout)this.CollectionViewLayout).ItemSize; 
      } 
      set 
      { 
       ((UICollectionViewFlowLayout)this.CollectionViewLayout).ItemSize = value; 
      } 
     } 


     public override UICollectionViewCell CellForItem(NSIndexPath indexPath) 
     { 
      if (indexPath == null) 
      { 
       //calling base.CellForItem(indexPath) when indexPath is null causes an exception. 
       //indexPath could be null in the following scenario: 
       // - GridView is configured to show 2 cells per row and there are 3 items in ItemsSource collection 
       // - you're trying to drag 4th cell (empty) like you're trying to scroll 
       return null; 
      } 
      return base.CellForItem(indexPath); 
     } 


     public override void Draw (CGRect rect) 
     { 
      this.CollectionViewLayout.InvalidateLayout(); 


      base.Draw (rect); 
     } 


     public override CGSize SizeThatFits(CGSize size) 
     { 
      return ItemSize; 
     } 
    } 
} 

Renderer Sınıf

GridViewRenderer.cs fazla bilgi Click here for custom class ve click here for renderer classiçin

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.Collections.Specialized; 
using System.Linq; 
using Foundation; 
using UIKit; 
using Xamarin.Forms; 
using Xamarin.Forms.Platform.iOS; 
using MyApp.Controls; 
using System.Collections.Generic; 


[assembly: ExportRenderer (typeof(GridView), typeof(GridViewRenderer))] 
namespace MyApp.Controls 
{ 
    public class GridViewRenderer: ViewRenderer<GridView,GridCollectionView> 
    { 
     private GridDataSource _dataSource; 

    public GridViewRenderer() 
     { 
     } 

     public int RowsInSection(UICollectionView collectionView, nint section) 
     { 
      return ((ICollection) this.Element.ItemsSource).Count; 
     } 

     public void ItemSelected(UICollectionView tableView, NSIndexPath indexPath) 
     { 
      var item = this.Element.ItemsSource.Cast<object>().ElementAt(indexPath.Row); 
      this.Element.InvokeItemSelectedEvent(this, item); 
     } 

     public UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath) 
     { 
      var item = this.Element.ItemsSource.Cast<object>().ElementAt(indexPath.Row); 
      var viewCellBinded = (this.Element.ItemTemplate.CreateContent() as ViewCell); 
      if (viewCellBinded == null) return null; 


      viewCellBinded.BindingContext = item; 
      return this.GetCell(collectionView, viewCellBinded, indexPath); 
     } 


     protected virtual UICollectionViewCell GetCell(UICollectionView collectionView, ViewCell item, NSIndexPath indexPath) 
     { 
      var collectionCell = collectionView.DequeueReusableCell(new NSString(GridViewCell.Key), indexPath) as GridViewCell; 


      if (collectionCell == null) return null; 


      collectionCell.ViewCell = item; 


      return collectionCell; 
     } 


     protected override void OnElementChanged (ElementChangedEventArgs<GridView> e) 
     { 
      base.OnElementChanged (e); 
      if (e.OldElement != null) 
      { 
       Unbind (e.OldElement); 
      } 
      if (e.NewElement != null) 
      { 
       if (Control == null) 
       { 
        var collectionView = new GridCollectionView() { 
         AllowsMultipleSelection = false, 
         SelectionEnable = e.NewElement.SelectionEnabled, 
         ContentInset = new UIEdgeInsets ((float)this.Element.Padding.Top, (float)this.Element.Padding.Left, (float)this.Element.Padding.Bottom, (float)this.Element.Padding.Right), 
         BackgroundColor = this.Element.BackgroundColor.ToUIColor(), 
         ItemSize = new CoreGraphics.CGSize ((float)this.Element.ItemWidth, (float)this.Element.ItemHeight), 
         RowSpacing = this.Element.RowSpacing, 
         ColumnSpacing = this.Element.ColumnSpacing 
        }; 


        Bind (e.NewElement); 


        collectionView.Source = this.DataSource; 
        //collectionView.Delegate = this.GridViewDelegate; 


        SetNativeControl (collectionView); 
       } 
      } 




     } 


     private void Unbind (GridView oldElement) 
     { 
      if (oldElement == null) return; 


      oldElement.PropertyChanging -= this.ElementPropertyChanging; 
      oldElement.PropertyChanged -= this.ElementPropertyChanged; 


      var itemsSource = oldElement.ItemsSource as INotifyCollectionChanged; 
      if (itemsSource != null) 
      { 
       itemsSource.CollectionChanged -= this.DataCollectionChanged; 
      } 
     } 


     private void Bind (GridView newElement) 
     { 
      if (newElement == null) return; 


      newElement.PropertyChanging += this.ElementPropertyChanging; 
      newElement.PropertyChanged += this.ElementPropertyChanged; 


      var source = newElement.ItemsSource as INotifyCollectionChanged; 
      if (source != null) 
      { 
       source.CollectionChanged += this.DataCollectionChanged; 
      } 
     } 


     private void ElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e) 
     { 
      if (e.PropertyName == GridView.ItemsSourceProperty.PropertyName) 
      { 
       var newItemsSource = this.Element.ItemsSource as INotifyCollectionChanged; 
       if (newItemsSource != null) 
       { 
        newItemsSource.CollectionChanged += DataCollectionChanged; 
        this.Control.ReloadData(); 
       } 
      } 
      else if(e.PropertyName == "ItemWidth" || e.PropertyName == "ItemHeight") 
      { 
       this.Control.ItemSize = new CoreGraphics.CGSize ((float)this.Element.ItemWidth, (float)this.Element.ItemHeight); 
      } 
     } 


     private void ElementPropertyChanging (object sender, PropertyChangingEventArgs e) 
     { 
      if (e.PropertyName == "ItemsSource") 
      { 
       var oldItemsSource = this.Element.ItemsSource as INotifyCollectionChanged; 
       if (oldItemsSource != null) 
       { 
        oldItemsSource.CollectionChanged -= DataCollectionChanged; 
       } 
      } 
     } 


     private void DataCollectionChanged (object sender, NotifyCollectionChangedEventArgs e) 
     { 
      InvokeOnMainThread (()=> { 
       try 
       { 
        if(this.Control == null) 
         return; 


        this.Control.ReloadData(); 


        // TODO: try to handle add or remove operations gracefully, just reload the whole collection for other changes 
        // InsertItems, DeleteItems or ReloadItems can cause 
        // *** Assertion failure in -[XLabs_Forms_Controls_GridCollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:], 
        // BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3512.30.14/UICollectionView.m:4324 


//     var indexes = new List<NSIndexPath>(); 
//     switch (e.Action) { 
//      case NotifyCollectionChangedAction.Add: 
//       for (int i = 0; i < e.NewItems.Count; i++) { 
//        indexes.Add(NSIndexPath.FromRowSection((nint)(e.NewStartingIndex + i),0)); 
//       } 
//       this.Control.InsertItems(indexes.ToArray()); 
//       break; 
//      case NotifyCollectionChangedAction.Remove: 
//       for (int i = 0; i< e.OldItems.Count; i++) { 
//        indexes.Add(NSIndexPath.FromRowSection((nint)(e.OldStartingIndex + i),0)); 
//       } 
//       this.Control.DeleteItems(indexes.ToArray()); 
//       break; 
//      default: 
//       this.Control.ReloadData(); 
//       break; 
//     } 
       } 
       catch { } // todo: determine why we are hiding a possible exception here 
      }); 
     } 

     private GridDataSource DataSource 
     { 
      get 
      { 
       return _dataSource ?? (_dataSource = new GridDataSource (GetCell, RowsInSection,ItemSelected)); 
      } 
     } 


     protected override void Dispose (bool disposing) 
     { 
      base.Dispose (disposing); 
      if (disposing && _dataSource != null) 
      { 
       Unbind (Element); 
       _dataSource.Dispose(); 
       _dataSource = null; 
      } 
     } 
    } 
} 
+0

Bağlantı için teşekkürler, ilginç. Hücreleri kaydettiriyor gibi görünmüyorlar, ama sadece onları yitiriyorlar. https://github.com/XLabs/Xamarin-Forms-Labs/blob/master/src/Forms/XLabs.Forms.iOS/Controls/GridView/GridViewRenderer.cs#L89 – RVandersteen

+0

Sanırım yalnızca bağlantı yanıtı için oy verdiniz . – RVandersteen

+0

@RVandersteen, Cevabımı güncelledim. –

İlgili konular