I am building an app with quite a number sub classed monotouch dialog RootElements . Part of customising the look and feel of the cell was adding a notification view on the far right of the cell based on boolean value bound from the viewmodel, as part of the validation of that specific cell.
This works great if all the cells never go out of view. But when scrolling comes into play, these UIViews added to the cells get mixed up.
I have tried overriding the CellKey getter and an assortment of other options to no avail, any assistance would be greatly appreciated. Thank you.
public class PgpStyledRootElement : RootElement, IElementSizing, IValidatableElement
{
float _height;
bool _isRequired = false;
UIView notificationView;
protected IMvxMessenger _messenger;
protected MvxSubscriptionToken _token;
public WeakReference WeakNotificationView { get; set;}
public UIView NotificationView
{
get
{
if (WeakNotificationView == null || !WeakNotificationView.IsAlive)
return null;
return WeakNotificationView.Target as UIView;
}
}
private UITableViewCell _activeCell;
public UITableViewCell ActiveCell
{
get
{
if(_activeCell == null)
{
_activeCell = this.GetActiveCell ();
}
return _activeCell;
}
set
{
_activeCell = value;
}
}
private bool _isValid = true;
public bool IsValid
{
get { return _isValid; }
set
{
_isValid = value;
if (_isValid)
{
UIApplication.SharedApplication.InvokeOnMainThread (RemoveNotificationView);
}
else
{
UIApplication.SharedApplication.InvokeOnMainThread (AddNotificationView);
}
}
}
public PgpStyledRootElement(string caption, bool isRequired, Group group = null) : base(caption, group) {
}
public PgpStyledRootElement(string caption, bool isRequired, float height, bool fullPageWidth, Group group = null) : base(caption, group) {
_height = height;
}
public PgpStyledRootElement(string caption, bool isRequired, float height, Group group = null, string defaultDetailText = null) : base(caption, group) {
_height = height;
_isRequired = isRequired;
_messenger = Mvx.Resolve<IMvxMessenger> ();
_token = _messenger.Subscribe<ScreenWillRotateMessage> (HandleScreenWillRotate);
}
public PgpStyledRootElement (string caption, bool isRequired, float height, Func<RootElement, UIViewController> createOnSelected) : base (caption, createOnSelected)
{
this.Sections = new List<Section> ();
_height = height;
_messenger = Mvx.Resolve<IMvxMessenger> ();
_token = _messenger.Subscribe<ScreenWillRotateMessage> (HandleScreenWillRotate);
}
public PgpStyledRootElement(string caption, float height, Group group = null) : base(caption, group) {
_height = height;
}
protected override UITableViewCell GetCellImpl (UITableView tv)
{
var cell = base.GetCellImpl (tv);
HandleInitialLoadValidation (cell);
return cell;
}
protected override void UpdateCellDisplay (UITableViewCell cell)
{
base.UpdateCellDisplay (cell);
if (cell != null) {
cell.TextLabel.TextColor = CaptureListingsStyleConfig.DefaultTableCellTextColor;
cell.SetNeedsLayout ();
}
}
public void HandleInitialLoadValidation (UITableViewCell cell)
{
if (_isRequired)
{
if (!IsValid)
{
AddInitialNotificationView (cell);
}
}
}
static void GetRequiredIndicatorFrame (UITableViewCell cell, out float indicatorPointX, out float indicatorHeight)
{
if (UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.Portrait || UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.PortraitUpsideDown) {
indicatorPointX = cell.Frame.Width + 120;
indicatorHeight = cell.Frame.Height;
}
else {
indicatorPointX = cell.Frame.Width * 2 + 56;
indicatorHeight = cell.Frame.Height;
}
}
static void GetRequiredIndicatorFrameForRotationChange (UITableViewCell cell, out float indicatorPointX, out float indicatorHeight)
{
if (UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.Portrait || UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.PortraitUpsideDown) {
indicatorPointX = cell.Frame.Width - 263;
indicatorHeight = cell.Frame.Height;
}
else {
indicatorPointX = cell.Frame.Width + 249;
indicatorHeight = cell.Frame.Height;
}
}
void HandleScreenWillRotate (ScreenWillRotateMessage obj)
{
RectangleF newFrame;
if(NotificationView != null)
{
const int indicatorpointY = 0;
const int indicatorWidth = 7;
float indicatorPointX;
float indicatorHeight;
GetRequiredIndicatorFrameForRotationChange (ActiveCell, out indicatorPointX, out indicatorHeight);
CreateNewNotificationViewFrame (out newFrame, indicatorpointY, indicatorWidth, indicatorPointX, indicatorHeight);
NotificationView.Frame = newFrame;
}
}
static void CreateNewNotificationViewFrame (out RectangleF newFrame, int indicatorpointY, int indicatorWidth, float indicatorPointX, float indicatorHeight)
{
newFrame = new RectangleF (indicatorPointX, indicatorpointY, indicatorWidth, indicatorHeight);
}
public void AddInitialNotificationView (UITableViewCell cell)
{
if (cell != null) {
const int indicatorpointY = 0;
const int indicatorWidth = 7;
float indicatorPointX;
float indicatorHeight;
GetRequiredIndicatorFrame (cell, out indicatorPointX, out indicatorHeight);
if (Util.UserInterfaceIdiomIsPhone) {
indicatorPointX = cell.Frame.Width - indicatorWidth;
}
AddViewToCell (cell, indicatorpointY, indicatorWidth, indicatorPointX, indicatorHeight);
}
}
public void AddNotificationView ()
{
if (ActiveCell != null) {
const int indicatorpointY = 0;
const int indicatorWidth = 7;
var indicatorPointX = ActiveCell.Frame.Width - indicatorWidth;
var indicatorHeight = ActiveCell.Frame.Height;
if (Util.UserInterfaceIdiomIsPhone) {
indicatorPointX = ActiveCell.Frame.Width - indicatorWidth;
}
AddViewToCell (ActiveCell, indicatorpointY, indicatorWidth, indicatorPointX, indicatorHeight);
}
}
void AddViewToCell (UITableViewCell cell, int indicatorpointY, int indicatorWidth, float indicatorPointX, float indicatorHeight)
{
if (NotificationView == null) {
notificationView = new UIView (new RectangleF (indicatorPointX, indicatorpointY, indicatorWidth, indicatorHeight));
notificationView.BackgroundColor = UIColor.Red;
WeakNotificationView = new WeakReference (notificationView);
cell.Add (NotificationView);
}
}
public void RemoveNotificationView()
{
if(NotificationView != null)
{
NotificationView.RemoveFromSuperview ();
WeakNotificationView = null; //This should technically not be necessary, but lets do it anyway
}
}
#region IElementSizing implementation
public float GetHeight (UITableView tableView, NSIndexPath indexPath)
{
if(_height == 0.0f)
return CaptureListingsStyleConfig.DefaultTextCellHeight; //return CaptureListingsStyleConfig.DefaultRootCellHeight ();
return _height;
}
#endregion
}