using System; using System.ComponentModel; using System.Diagnostics; #if __UNIFIED__ using UIKit; #else using MonoTouch.UIKit; using System.Drawing; #endif #if __UNIFIED__ using RectangleF = CoreGraphics.CGRect; using SizeF = CoreGraphics.CGSize; using PointF = CoreGraphics.CGPoint; #else using nfloat=System.Single; using nint=System.Int32; using nuint=System.UInt32; #endif namespace Xamarin.Forms.Platform.iOS { public class ViewCellRenderer : CellRenderer { public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv) { var viewCell = (ViewCell)item; var cell = reusableCell as ViewTableCell; if (cell == null) cell = new ViewTableCell(item.GetType().FullName); else cell.ViewCell.PropertyChanged -= ViewCellPropertyChanged; viewCell.PropertyChanged += ViewCellPropertyChanged; cell.ViewCell = viewCell; WireUpForceUpdateSizeRequested(item, cell, tv); UpdateBackground(cell, item); UpdateIsEnabled(cell, viewCell); return cell; } static void UpdateIsEnabled(ViewTableCell cell, ViewCell viewCell) { cell.UserInteractionEnabled = viewCell.IsEnabled; cell.TextLabel.Enabled = viewCell.IsEnabled; } void ViewCellPropertyChanged(object sender, PropertyChangedEventArgs e) { var viewCell = (ViewCell)sender; var realCell = (ViewTableCell)GetRealCell(viewCell); if (e.PropertyName == Cell.IsEnabledProperty.PropertyName) UpdateIsEnabled(realCell, viewCell); } internal class ViewTableCell : UITableViewCell, INativeElementView { WeakReference _rendererRef; ViewCell _viewCell; public ViewTableCell(string key) : base(UITableViewCellStyle.Default, key) { } public ViewCell ViewCell { get { return _viewCell; } set { if (_viewCell == value) return; UpdateCell(value); } } Element INativeElementView.Element { get { return ViewCell; } } public override void LayoutSubviews() { //This sets the content views frame. base.LayoutSubviews(); var contentFrame = ContentView.Frame; Layout.LayoutChildIntoBoundingRegion(ViewCell.View, contentFrame.ToRectangle()); if (_rendererRef == null) return; IVisualElementRenderer renderer; if (_rendererRef.TryGetTarget(out renderer)) renderer.NativeView.Frame = contentFrame; } public override SizeF SizeThatFits(SizeF size) { IVisualElementRenderer renderer; if (!_rendererRef.TryGetTarget(out renderer)) return base.SizeThatFits(size); double width = size.Width; var height = size.Height > 0 ? size.Height : double.PositiveInfinity; var result = renderer.Element.Measure(width, height); // make sure to add in the separator return new SizeF(size.Width, (float)result.Request.Height + 1f / UIScreen.MainScreen.Scale); } protected override void Dispose(bool disposing) { if (disposing) { IVisualElementRenderer renderer; if (_rendererRef != null && _rendererRef.TryGetTarget(out renderer) && renderer.Element != null) { var platform = renderer.Element.Platform as Platform; if (platform != null) platform.DisposeModelAndChildrenRenderers(renderer.Element); _rendererRef = null; } } base.Dispose(disposing); } IVisualElementRenderer GetNewRenderer() { var newRenderer = Platform.CreateRenderer(_viewCell.View); _rendererRef = new WeakReference(newRenderer); ContentView.AddSubview(newRenderer.NativeView); return newRenderer; } void UpdateCell(ViewCell cell) { if (_viewCell != null) Device.BeginInvokeOnMainThread(_viewCell.SendDisappearing); _viewCell = cell; Device.BeginInvokeOnMainThread(_viewCell.SendAppearing); IVisualElementRenderer renderer; if (_rendererRef == null || !_rendererRef.TryGetTarget(out renderer)) renderer = GetNewRenderer(); else { if (renderer.Element != null && renderer == Platform.GetRenderer(renderer.Element)) renderer.Element.ClearValue(Platform.RendererProperty); var type = Registrar.Registered.GetHandlerType(_viewCell.View.GetType()); if (renderer.GetType() == type || (renderer is Platform.DefaultRenderer && type == null)) renderer.SetElement(_viewCell.View); else { //when cells are getting reused the element could be already set to another cell //so we should dispose based on the renderer and not the renderer.Element var platform = renderer.Element.Platform as Platform; platform.DisposeRendererAndChildren(renderer); renderer = GetNewRenderer(); } } Platform.SetRenderer(_viewCell.View, renderer); } } } }