diff options
Diffstat (limited to 'Xamarin.Forms.Platform.MacOS/Cells')
9 files changed, 764 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.MacOS/Cells/CellNSView.cs b/Xamarin.Forms.Platform.MacOS/Cells/CellNSView.cs new file mode 100644 index 00000000..1ba964ee --- /dev/null +++ b/Xamarin.Forms.Platform.MacOS/Cells/CellNSView.cs @@ -0,0 +1,167 @@ +using System; +using System.ComponentModel; +using AppKit; +using CoreGraphics; + +namespace Xamarin.Forms.Platform.MacOS +{ + internal class CellNSView : NSView, INativeElementView + { + static readonly NSColor s_defaultChildViewsBackground = NSColor.Clear; + static readonly CGColor s_defaultHeaderViewsBackground = NSColor.LightGray.CGColor; + Cell _cell; + readonly NSTableViewCellStyle _style; + + public Action<object, PropertyChangedEventArgs> PropertyChanged; + + public CellNSView(NSTableViewCellStyle style) + { + WantsLayer = true; + _style = style; + CreateUI(); + } + + public NSTextField TextLabel { get; private set; } + + public NSTextField DetailTextLabel { get; private set; } + + public NSImageView ImageView { get; private set; } + + public NSView AccessoryView { get; private set; } + + public Element Element => Cell; + + public Cell Cell + { + get { return _cell; } + set + { + if (_cell == value) + return; + + ICellController cellController = _cell; + + if (cellController != null) + Device.BeginInvokeOnMainThread(cellController.SendDisappearing); + + _cell = value; + cellController = value; + + if (cellController != null) + Device.BeginInvokeOnMainThread(cellController.SendAppearing); + } + } + + public void HandlePropertyChanged(object sender, PropertyChangedEventArgs e) + { + PropertyChanged?.Invoke(this, e); + } + + public override void Layout() + { + const int padding = 10; + nfloat availableHeight = Frame.Height; + nfloat availableWidth = Frame.Width - padding * 2; + nfloat imageWidth = 0; + nfloat accessoryViewWidth = 0; + + if (ImageView != null) + { + nfloat imageHeight = imageWidth = availableHeight; + ImageView.Frame = new CGRect(padding, 0, imageWidth, imageHeight); + } + + if (AccessoryView != null) + { + accessoryViewWidth = _style == NSTableViewCellStyle.Value1 ? 50 : availableWidth - 100; + AccessoryView.Frame = new CGRect(availableWidth - accessoryViewWidth + padding, 0, accessoryViewWidth, + availableHeight); + foreach (var subView in AccessoryView.Subviews) + { + //try to find the size the control wants, if no width use default width + var size = subView.FittingSize; + if (size.Width == 0) + size.Width = accessoryViewWidth; + + var x = AccessoryView.Bounds.Width - size.Width; + var y = (AccessoryView.Bounds.Height - size.Height) / 2; + subView.Frame = new CGRect(new CGPoint(x, y), size); + } + } + + nfloat labelHeights = availableHeight; + nfloat labelWidth = availableWidth - imageWidth - accessoryViewWidth; + + if (!string.IsNullOrEmpty(DetailTextLabel?.StringValue)) + { + labelHeights = availableHeight / 2; + DetailTextLabel.CenterTextVertically(new CGRect(imageWidth + padding, 0, labelWidth, labelHeights)); + } + + TextLabel.CenterTextVertically(new CGRect(imageWidth + padding, availableHeight - labelHeights, labelWidth, + labelHeights)); + base.Layout(); + } + + internal static NSView GetNativeCell(NSTableView tableView, Cell cell, string templateId = "", bool isHeader = false, + bool isRecycle = false) + { + var reusable = tableView.MakeView(templateId, tableView); + NSView nativeCell; + if (reusable == null || !isRecycle) + { + var renderer = (CellRenderer)Registrar.Registered.GetHandler(cell.GetType()); + nativeCell = renderer.GetCell(cell, null, tableView); + } + else + { + nativeCell = reusable; + } + + if (string.IsNullOrEmpty(nativeCell.Identifier)) + nativeCell.Identifier = templateId; + + if (!isHeader) return nativeCell; + if (nativeCell.Layer != null) nativeCell.Layer.BackgroundColor = s_defaultHeaderViewsBackground; + return nativeCell; + } + + void CreateUI() + { + var style = _style; + + AddSubview(TextLabel = new NSTextField + { + Bordered = false, + Selectable = false, + Editable = false, + Font = NSFont.LabelFontOfSize(NSFont.SystemFontSize) + }); + + TextLabel.Cell.BackgroundColor = s_defaultChildViewsBackground; + + if (style == NSTableViewCellStyle.Image || style == NSTableViewCellStyle.Subtitle || + style == NSTableViewCellStyle.ImageSubtitle) + { + AddSubview(DetailTextLabel = new NSTextField + { + Bordered = false, + Selectable = false, + Editable = false, + Font = NSFont.LabelFontOfSize(NSFont.SmallSystemFontSize) + }); + DetailTextLabel.Cell.BackgroundColor = s_defaultChildViewsBackground; + } + + if (style == NSTableViewCellStyle.Image || style == NSTableViewCellStyle.ImageSubtitle) + AddSubview(ImageView = new NSImageView()); + + if (style == NSTableViewCellStyle.Value1 || style == NSTableViewCellStyle.Value2) + { + var accessoryView = new NSView { WantsLayer = true }; + accessoryView.Layer.BackgroundColor = s_defaultChildViewsBackground.CGColor; + AddSubview(AccessoryView = accessoryView); + } + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.MacOS/Cells/CellRenderer.cs b/Xamarin.Forms.Platform.MacOS/Cells/CellRenderer.cs new file mode 100644 index 00000000..54e540a6 --- /dev/null +++ b/Xamarin.Forms.Platform.MacOS/Cells/CellRenderer.cs @@ -0,0 +1,68 @@ +using System; +using AppKit; +using CoreGraphics; + +namespace Xamarin.Forms.Platform.MacOS +{ + public class CellRenderer : IRegisterable + { + static readonly BindableProperty s_realCellProperty = BindableProperty.CreateAttached("RealCell", typeof(NSView), + typeof(Cell), null); + + EventHandler _onForceUpdateSizeRequested; + + public virtual NSView GetCell(Cell item, NSView reusableView, NSTableView tv) + { + var tvc = reusableView as CellNSView ?? new CellNSView(NSTableViewCellStyle.Default); + + tvc.Cell = item; + + WireUpForceUpdateSizeRequested(item, tvc, tv); + + tvc.TextLabel.StringValue = item.ToString(); + + UpdateBackground(tvc, item); + + return tvc; + } + + protected void UpdateBackground(NSView tableViewCell, Cell cell) + { + tableViewCell.WantsLayer = true; + var bgColor = NSColor.White; + var element = cell.RealParent as VisualElement; + if (element != null) + bgColor = element.BackgroundColor == Color.Default ? bgColor : element.BackgroundColor.ToNSColor(); + + UpdateBackgroundChild(cell, bgColor); + + tableViewCell.Layer.BackgroundColor = bgColor.CGColor; + } + + protected void WireUpForceUpdateSizeRequested(ICellController cell, NSView nativeCell, NSTableView tableView) + { + cell.ForceUpdateSizeRequested -= _onForceUpdateSizeRequested; + + _onForceUpdateSizeRequested = (sender, e) => + { + //TODO: Implement ForceUpdateSize + }; + + cell.ForceUpdateSizeRequested += _onForceUpdateSizeRequested; + } + + internal virtual void UpdateBackgroundChild(Cell cell, NSColor backgroundColor) + { + } + + internal static NSView GetRealCell(BindableObject cell) + { + return (NSView)cell.GetValue(s_realCellProperty); + } + + internal static void SetRealCell(BindableObject cell, NSView renderer) + { + cell.SetValue(s_realCellProperty, renderer); + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.MacOS/Cells/EntryCellRenderer.cs b/Xamarin.Forms.Platform.MacOS/Cells/EntryCellRenderer.cs new file mode 100644 index 00000000..43789dcc --- /dev/null +++ b/Xamarin.Forms.Platform.MacOS/Cells/EntryCellRenderer.cs @@ -0,0 +1,144 @@ +using System; +using System.ComponentModel; +using AppKit; +using CoreGraphics; +using Foundation; + +namespace Xamarin.Forms.Platform.MacOS +{ + public class EntryCellRenderer : CellRenderer + { + static readonly Color s_defaultTextColor = Color.Black; + + public override NSView GetCell(Cell item, NSView reusableView, NSTableView tv) + { + NSTextField nsEntry = null; + var tvc = reusableView as CellNSView; + if (tvc == null) + tvc = new CellNSView(NSTableViewCellStyle.Value2); + else + { + tvc.Cell.PropertyChanged -= OnCellPropertyChanged; + + nsEntry = tvc.AccessoryView.Subviews[0] as NSTextField; + if (nsEntry != null) + { + nsEntry.RemoveFromSuperview(); + nsEntry.Changed -= OnTextFieldTextChanged; + } + } + + SetRealCell(item, tvc); + + if (nsEntry == null) + tvc.AccessoryView.AddSubview(nsEntry = new NSTextField()); + + var entryCell = (EntryCell)item; + + tvc.Cell = item; + tvc.Cell.PropertyChanged += OnCellPropertyChanged; + nsEntry.Changed += OnTextFieldTextChanged; + + WireUpForceUpdateSizeRequested(item, tvc, tv); + + UpdateBackground(tvc, entryCell); + UpdateLabel(tvc, entryCell); + UpdateText(tvc, entryCell); + UpdatePlaceholder(tvc, entryCell); + UpdateLabelColor(tvc, entryCell); + UpdateHorizontalTextAlignment(tvc, entryCell); + UpdateIsEnabled(tvc, entryCell); + + return tvc; + } + + internal override void UpdateBackgroundChild(Cell cell, NSColor backgroundColor) + { + var realCell = (CellNSView)GetRealCell(cell); + + var nsTextField = realCell.AccessoryView.Subviews[0] as NSTextField; + if (nsTextField != null) + nsTextField.BackgroundColor = backgroundColor; + + base.UpdateBackgroundChild(cell, backgroundColor); + } + + static void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e) + { + var entryCell = (EntryCell)sender; + var realCell = (CellNSView)GetRealCell(entryCell); + + if (e.PropertyName == EntryCell.LabelProperty.PropertyName) + UpdateLabel(realCell, entryCell); + else if (e.PropertyName == EntryCell.TextProperty.PropertyName) + UpdateText(realCell, entryCell); + else if (e.PropertyName == EntryCell.PlaceholderProperty.PropertyName) + UpdatePlaceholder(realCell, entryCell); + else if (e.PropertyName == EntryCell.LabelColorProperty.PropertyName) + UpdateLabelColor(realCell, entryCell); + else if (e.PropertyName == EntryCell.HorizontalTextAlignmentProperty.PropertyName) + UpdateHorizontalTextAlignment(realCell, entryCell); + else if (e.PropertyName == Cell.IsEnabledProperty.PropertyName) + UpdateIsEnabled(realCell, entryCell); + } + + static void OnTextFieldTextChanged(object sender, EventArgs eventArgs) + { + var notification = (NSNotification)sender; + var view = (NSView)notification.Object; + var field = (NSTextField)view; + + CellNSView realCell = null; + while (view.Superview != null && realCell == null) + { + view = view.Superview; + realCell = view as CellNSView; + } + + if (realCell != null) + ((EntryCell)realCell.Cell).Text = field.StringValue; + } + + static void UpdateHorizontalTextAlignment(CellNSView cell, EntryCell entryCell) + { + var nsTextField = cell.AccessoryView.Subviews[0] as NSTextField; + if (nsTextField != null) + nsTextField.Alignment = entryCell.HorizontalTextAlignment.ToNativeTextAlignment(); + } + + static void UpdateIsEnabled(CellNSView cell, EntryCell entryCell) + { + cell.TextLabel.Enabled = entryCell.IsEnabled; + var nsTextField = cell.AccessoryView.Subviews[0] as NSTextField; + if (nsTextField != null) + nsTextField.Enabled = entryCell.IsEnabled; + } + + static void UpdateLabel(CellNSView cell, EntryCell entryCell) + { + cell.TextLabel.StringValue = entryCell.Label ?? ""; + } + + static void UpdateLabelColor(CellNSView cell, EntryCell entryCell) + { + cell.TextLabel.TextColor = entryCell.LabelColor.ToNSColor(s_defaultTextColor); + } + + static void UpdatePlaceholder(CellNSView cell, EntryCell entryCell) + { + var nsTextField = cell.AccessoryView.Subviews[0] as NSTextField; + if (nsTextField != null) + nsTextField.PlaceholderString = entryCell.Placeholder ?? ""; + } + + static void UpdateText(CellNSView cell, EntryCell entryCell) + { + var nsTextField = cell.AccessoryView.Subviews[0] as NSTextField; + if (nsTextField != null && nsTextField.StringValue == entryCell.Text) + return; + + if (nsTextField != null) + nsTextField.StringValue = entryCell.Text ?? ""; + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.MacOS/Cells/ImageCellRenderer.cs b/Xamarin.Forms.Platform.MacOS/Cells/ImageCellRenderer.cs new file mode 100644 index 00000000..8bd76772 --- /dev/null +++ b/Xamarin.Forms.Platform.MacOS/Cells/ImageCellRenderer.cs @@ -0,0 +1,68 @@ +using System.ComponentModel; +using System.Threading.Tasks; +using AppKit; +using Foundation; + +namespace Xamarin.Forms.Platform.MacOS +{ + public class ImageCellRenderer : TextCellRenderer + { + public override NSView GetCell(Cell item, NSView reusableView, NSTableView tv) + { + var tvc = reusableView as CellNSView ?? new CellNSView(NSTableViewCellStyle.ImageSubtitle); + + var result = (CellNSView)base.GetCell(item, tvc, tv); + + var imageCell = (ImageCell)item; + + WireUpForceUpdateSizeRequested(item, result, tv); + +#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed + SetImage(imageCell, result); +#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed + + return result; + } + + protected override async void HandlePropertyChanged(object sender, PropertyChangedEventArgs args) + { + var tvc = (CellNSView)sender; + var imageCell = (ImageCell)tvc.Cell; + + base.HandlePropertyChanged(sender, args); + + if (args.PropertyName == ImageCell.ImageSourceProperty.PropertyName) + await SetImage(imageCell, tvc); + } + + static async Task SetImage(ImageCell cell, CellNSView target) + { + var source = cell.ImageSource; + + target.ImageView.Image = null; + + IImageSourceHandler handler; + + if (source != null && (handler = Registrar.Registered.GetHandler<IImageSourceHandler>(source.GetType())) != null) + { + NSImage uiimage; + try + { + uiimage = await handler.LoadImageAsync(source).ConfigureAwait(false); + } + catch (TaskCanceledException) + { + uiimage = null; + } + + NSRunLoop.Main.BeginInvokeOnMainThread(() => + { + target.ImageView.Image = uiimage; + target.NeedsLayout = true; + }); + } + else + target.ImageView.Image = null; + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.MacOS/Cells/NSTableViewCellStyle.cs b/Xamarin.Forms.Platform.MacOS/Cells/NSTableViewCellStyle.cs new file mode 100644 index 00000000..3e0235d4 --- /dev/null +++ b/Xamarin.Forms.Platform.MacOS/Cells/NSTableViewCellStyle.cs @@ -0,0 +1,12 @@ +namespace Xamarin.Forms.Platform.MacOS +{ + internal enum NSTableViewCellStyle + { + Default, + Value1, + Value2, + Subtitle, + Image, + ImageSubtitle + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.MacOS/Cells/SwitchCellRenderer.cs b/Xamarin.Forms.Platform.MacOS/Cells/SwitchCellRenderer.cs new file mode 100644 index 00000000..5f086b49 --- /dev/null +++ b/Xamarin.Forms.Platform.MacOS/Cells/SwitchCellRenderer.cs @@ -0,0 +1,88 @@ +using System; +using System.ComponentModel; +using AppKit; + +namespace Xamarin.Forms.Platform.MacOS +{ + public class SwitchCellRenderer : CellRenderer + { + public override NSView GetCell(Cell item, NSView reusableView, NSTableView tv) + { + var tvc = reusableView as CellNSView; + NSButton nsSwitch = null; + if (tvc == null) + tvc = new CellNSView(NSTableViewCellStyle.Value1); + else + { + nsSwitch = tvc.AccessoryView.Subviews[0] as NSButton; + if (nsSwitch != null) + { + nsSwitch.RemoveFromSuperview(); + nsSwitch.Activated -= OnSwitchValueChanged; + } + tvc.Cell.PropertyChanged -= OnCellPropertyChanged; + } + + SetRealCell(item, tvc); + + if (nsSwitch == null) + { + nsSwitch = new NSButton { AllowsMixedState = false, Title = string.Empty }; + nsSwitch.SetButtonType(NSButtonType.Switch); + } + + var boolCell = (SwitchCell)item; + + tvc.Cell = item; + tvc.Cell.PropertyChanged += OnCellPropertyChanged; + tvc.AccessoryView.AddSubview(nsSwitch); + tvc.TextLabel.StringValue = boolCell.Text ?? ""; + + nsSwitch.State = boolCell.On ? NSCellStateValue.On : NSCellStateValue.Off; + nsSwitch.Activated += OnSwitchValueChanged; + WireUpForceUpdateSizeRequested(item, tvc, tv); + + UpdateBackground(tvc, item); + UpdateIsEnabled(tvc, boolCell); + + return tvc; + } + + static void UpdateIsEnabled(CellNSView cell, SwitchCell switchCell) + { + cell.TextLabel.Enabled = switchCell.IsEnabled; + var uiSwitch = cell.AccessoryView.Subviews[0] as NSButton; + if (uiSwitch != null) + uiSwitch.Enabled = switchCell.IsEnabled; + } + + void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e) + { + var boolCell = (SwitchCell)sender; + var realCell = (CellNSView)GetRealCell(boolCell); + + if (e.PropertyName == SwitchCell.OnProperty.PropertyName) + ((NSButton)realCell.AccessoryView.Subviews[0]).State = boolCell.On ? NSCellStateValue.On : NSCellStateValue.Off; + else if (e.PropertyName == SwitchCell.TextProperty.PropertyName) + realCell.TextLabel.StringValue = boolCell.Text ?? ""; + else if (e.PropertyName == Cell.IsEnabledProperty.PropertyName) + UpdateIsEnabled(realCell, boolCell); + } + + void OnSwitchValueChanged(object sender, EventArgs eventArgs) + { + var view = (NSView)sender; + var sw = (NSButton)view; + + CellNSView realCell = null; + while (view.Superview != null && realCell == null) + { + view = view.Superview; + realCell = view as CellNSView; + } + + if (realCell != null) + ((SwitchCell)realCell.Cell).On = sw.State == NSCellStateValue.On; + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.MacOS/Cells/TextCellRenderer.cs b/Xamarin.Forms.Platform.MacOS/Cells/TextCellRenderer.cs new file mode 100644 index 00000000..6e36ce7d --- /dev/null +++ b/Xamarin.Forms.Platform.MacOS/Cells/TextCellRenderer.cs @@ -0,0 +1,66 @@ +using System.ComponentModel; +using AppKit; + +namespace Xamarin.Forms.Platform.MacOS +{ + public class TextCellRenderer : CellRenderer + { + static readonly Color s_defaultDetailColor = new Color(.32, .4, .57); + static readonly Color s_defaultTextColor = Color.Black; + + public override NSView GetCell(Cell item, NSView reusableView, NSTableView tv) + { + var textCell = (TextCell)item; + + var tvc = reusableView as CellNSView ?? new CellNSView(NSTableViewCellStyle.Subtitle); + + if (tvc.Cell != null) + tvc.Cell.PropertyChanged -= tvc.HandlePropertyChanged; + + tvc.Cell = textCell; + textCell.PropertyChanged += tvc.HandlePropertyChanged; + tvc.PropertyChanged = HandlePropertyChanged; + + tvc.TextLabel.StringValue = textCell.Text ?? ""; + tvc.DetailTextLabel.StringValue = textCell.Detail ?? ""; + tvc.TextLabel.TextColor = textCell.TextColor.ToNSColor(s_defaultTextColor); + tvc.DetailTextLabel.TextColor = textCell.DetailColor.ToNSColor(s_defaultDetailColor); + + WireUpForceUpdateSizeRequested(item, tvc, tv); + + UpdateIsEnabled(tvc, textCell); + + UpdateBackground(tvc, item); + + return tvc; + } + + protected virtual void HandlePropertyChanged(object sender, PropertyChangedEventArgs args) + { + var tvc = (CellNSView)sender; + var textCell = (TextCell)tvc.Cell; + if (args.PropertyName == TextCell.TextProperty.PropertyName) + { + tvc.TextLabel.StringValue = textCell.Text ?? ""; + tvc.TextLabel.SizeToFit(); + } + else if (args.PropertyName == TextCell.DetailProperty.PropertyName) + { + tvc.DetailTextLabel.StringValue = textCell.Detail ?? ""; + tvc.DetailTextLabel.SizeToFit(); + } + else if (args.PropertyName == TextCell.TextColorProperty.PropertyName) + tvc.TextLabel.TextColor = textCell.TextColor.ToNSColor(s_defaultTextColor); + else if (args.PropertyName == TextCell.DetailColorProperty.PropertyName) + tvc.DetailTextLabel.TextColor = textCell.DetailColor.ToNSColor(s_defaultTextColor); + else if (args.PropertyName == Cell.IsEnabledProperty.PropertyName) + UpdateIsEnabled(tvc, textCell); + } + + static void UpdateIsEnabled(CellNSView cell, TextCell entryCell) + { + cell.TextLabel.Enabled = entryCell.IsEnabled; + cell.DetailTextLabel.Enabled = entryCell.IsEnabled; + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.MacOS/Cells/ViewCellNSView.cs b/Xamarin.Forms.Platform.MacOS/Cells/ViewCellNSView.cs new file mode 100644 index 00000000..0dd766a2 --- /dev/null +++ b/Xamarin.Forms.Platform.MacOS/Cells/ViewCellNSView.cs @@ -0,0 +1,105 @@ +using System; +using AppKit; +using RectangleF = CoreGraphics.CGRect; + +namespace Xamarin.Forms.Platform.MacOS +{ + public class ViewCellNSView : NSView, INativeElementView + { + WeakReference<IVisualElementRenderer> _rendererRef; + + ViewCell _viewCell; + + public Element Element => ViewCell; + + public ViewCell ViewCell + { + get { return _viewCell; } + set + { + if (_viewCell == value) + return; + UpdateCell(value); + } + } + + public override void Layout() + { + LayoutSubviews(); + base.Layout(); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + IVisualElementRenderer renderer; + if (_rendererRef != null && _rendererRef.TryGetTarget(out renderer) && renderer.Element != null) + { + Platform.DisposeModelAndChildrenRenderers(renderer.Element); + + _rendererRef = null; + } + } + + base.Dispose(disposing); + } + + void LayoutSubviews() + { + var contentFrame = Frame; + var view = ViewCell.View; + + Xamarin.Forms.Layout.LayoutChildIntoBoundingRegion(view, contentFrame.ToRectangle()); + + if (_rendererRef == null) + return; + + IVisualElementRenderer renderer; + if (_rendererRef.TryGetTarget(out renderer)) + renderer.NativeView.Frame = view.Bounds.ToRectangleF(); + } + + IVisualElementRenderer GetNewRenderer() + { + var newRenderer = Platform.CreateRenderer(_viewCell.View); + _rendererRef = new WeakReference<IVisualElementRenderer>(newRenderer); + AddSubview(newRenderer.NativeView); + return newRenderer; + } + + void UpdateCell(ViewCell cell) + { + ICellController cellController = _viewCell; + if (cellController != null) + Device.BeginInvokeOnMainThread(cellController.SendDisappearing); + + _viewCell = cell; + cellController = cell; + + Device.BeginInvokeOnMainThread(cellController.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 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 + Platform.DisposeRendererAndChildren(renderer); + renderer = GetNewRenderer(); + } + } + + Platform.SetRenderer(_viewCell.View, renderer); + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.MacOS/Cells/ViewCellRenderer.cs b/Xamarin.Forms.Platform.MacOS/Cells/ViewCellRenderer.cs new file mode 100644 index 00000000..8b345181 --- /dev/null +++ b/Xamarin.Forms.Platform.MacOS/Cells/ViewCellRenderer.cs @@ -0,0 +1,46 @@ +using System.ComponentModel; +using AppKit; + +// ReSharper disable UnusedParameter.Local + +namespace Xamarin.Forms.Platform.MacOS +{ + public class ViewCellRenderer : CellRenderer + { + public override NSView GetCell(Cell item, NSView reusableView, NSTableView tv) + { + var viewCell = (ViewCell)item; + + var cell = reusableView as ViewCellNSView; + if (cell == null) + cell = new ViewCellNSView(); + else + cell.ViewCell.PropertyChanged -= ViewCellPropertyChanged; + + viewCell.PropertyChanged += ViewCellPropertyChanged; + cell.ViewCell = viewCell; + + SetRealCell(item, cell); + + WireUpForceUpdateSizeRequested(item, cell, tv); + + UpdateBackground(cell, item); + UpdateIsEnabled(cell, viewCell); + return cell; + } + + static void UpdateIsEnabled(ViewCellNSView cell, ViewCell viewCell) + { + //TODO: Implement IsEnabled on ViewCell + } + + static void ViewCellPropertyChanged(object sender, PropertyChangedEventArgs e) + { + var viewCell = (ViewCell)sender; + var realCell = (ViewCellNSView)GetRealCell(viewCell); + + if (e.PropertyName == Cell.IsEnabledProperty.PropertyName) + UpdateIsEnabled(realCell, viewCell); + } + } +}
\ No newline at end of file |