Xamarin iOS TableView Checkmark行也会检查其他行

时间:2018-11-07 15:10:47

标签: uitableview xamarin xamarin.ios

我有一个TableView,用户可以在其中检查多行。 现在我有一个问题,当我选择例如列表中的第5个元素和第5个元素也会被自动检查,但我无法解释原因。

我在TableViewSource基类中使用以下代码:

public abstract class BaseChecklistTableViewSource : UITableViewSource
{
    protected int checkCount;

    public BaseChecklistTableViewSource()
    {
    }

    public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
    {
        var cell = tableView.CellAt(indexPath);

        if (indexPath.Row >= 0)
        {
            if (cell.Accessory == UITableViewCellAccessory.None)
            {
                cell.Accessory = UITableViewCellAccessory.Checkmark;
                checkCount++;
            }
            else if (cell.Accessory == UITableViewCellAccessory.Checkmark)
            {
                cell.Accessory = UITableViewCellAccessory.None;
                checkCount--;
            }

            CheckCheckCount();

        }
    }

    protected void CheckCheckCount()
    {
        if (checkCount > 0)
        {
            EnableDoneButton();
        }
        else if (checkCount == 0)
        {
            DisableDoneButton();
        }
    }

    protected abstract void EnableDoneButton();
    protected abstract void DisableDoneButton();
}

这是“ BaseChecklistTableViewSource”具体类的代码:

public partial class CheckunitTableViewSource : BaseChecklistTableViewSource
{
    ListCheckunitController controller;
    private IEnumerable<Checkunit> existingCheckunits;

    public CheckunitTableViewSource(ListCheckunitController controller)
    {
        this.controller = controller;
        this.existingCheckunits = new List<Checkunit>();
    }

    public CheckunitTableViewSource(ListCheckunitController controller, IEnumerable<Checkunit> existingCheckunits) : this(controller)
    {
        if (existingCheckunits == null || !existingCheckunits.Any())
        {
            throw new ArgumentNullException(nameof(existingCheckunits));
        }

        this.existingCheckunits = existingCheckunits;
        checkCount = this.existingCheckunits.Count();

        CheckCheckCount();
    }

    // Returns the number of rows in each section of the table
    public override nint RowsInSection(UITableView tableview, nint section)
    {
        if (controller.Checkunits == null)
        {
            return 0;
        }
        return controller.Checkunits.Count();
    }
    //
    // Returns a table cell for the row indicated by row property of the NSIndexPath
    // This method is called multiple times to populate each row of the table.
    // The method automatically uses cells that have scrolled off the screen or creates new ones as necessary.
    //
    public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
    {
        var cell = tableView.DequeueReusableCell("checkunitViewCell") ?? new UITableViewCell();
        int row = indexPath.Row;
        var element = controller.Checkunits.ElementAt(row);

        if(existingCheckunits.FirstOrDefault(e => e.Id == element.Id) != null)
        {
            cell.Accessory = UITableViewCellAccessory.Checkmark;
        }

        //if(cell.Accessory == UITableViewCellAccessory.Checkmark)
        //{
        //    checkCount++;
        //}


        cell.TextLabel.Text = $"{element.Order}. {element.Designation}";
        cell.Tag = element.Id;
        return cell;
    }

    protected override void EnableDoneButton()
    {
        controller.EnableDoneButton();
    }

    protected override void DisableDoneButton()
    {
        controller.DisableDoneButton();
    }
}

我试图在RowSelected方法中使用一个断点,但是该断点只会被击中一次!

这是TableViewController的代码:

public partial class ListCheckunitController : BaseTableViewController
{
    private ImmobilePerpetration masterModel;
    private LoadingOverlay loadingOverlay;
    public IEnumerable<Checkunit> Checkunits { get; set; }

    public IEnumerable<Checkunit> existingCheckunits;
    public IEnumerable<CheckpointAssessment> existingAssessments;
    public static readonly NSString callHistoryCellId = new NSString("checkunitViewCell");
    UIRefreshControl refreshControl;
    private UIBarButtonItem doneButton;

    public ListCheckunitController(IntPtr handle) : base(handle)
    {
        existingCheckunits = new List<Checkunit>();
        existingAssessments = new List<CheckpointAssessment>();
    }

    public void Initialize(ImmobilePerpetration masterModel)
    {
        if (masterModel == null)
        {
            throw new ArgumentNullException(nameof(masterModel));
        }

        this.masterModel = masterModel;
    }

    public void Initialize(ImmobilePerpetration masterModel, IEnumerable<CheckpointAssessment> existingAssessments, IEnumerable<Checkunit> existingCheckunits)
    {
        Initialize(masterModel);

        if(existingAssessments == null || !existingAssessments.Any())
        {
            throw new ArgumentNullException(nameof(existingAssessments));
        }

        if (existingCheckunits == null || !existingCheckunits.Any())
        {
            throw new ArgumentNullException(nameof(existingCheckunits));
        }

        this.existingAssessments = existingAssessments;
        this.existingCheckunits = existingCheckunits;
    }

    async Task RefreshAsync(bool onlineSync)
    {
        InvokeOnMainThread(() => refreshControl.BeginRefreshing());
        try
        {
            var syncCtrl = new SynchronizationControllerAsync();
            Checkunits = await syncCtrl.SynchronizeCheckUnitAsync(onlineSync).ConfigureAwait(false);
        }
        catch (Exception e)
        {
            InvokeOnMainThread(() => { AlertHelper.ShowError(e.Message, this);});
        }

        InvokeOnMainThread(() =>
        {
            ListCheckunitTable.ReloadData();
            refreshControl.EndRefreshing();
        });

    }

    void AddRefreshControl()
    {
        refreshControl = new UIRefreshControl();
        refreshControl.ValueChanged += async (sender, e) =>
        {
            await RefreshAsync(true).ConfigureAwait(false);
        };
    }

    public override async void ViewDidLoad()
    {
        var bounds = UIScreen.MainScreen.Bounds;
        loadingOverlay = new LoadingOverlay(bounds);
        View.Add(loadingOverlay);

        AddRefreshControl();
        await RefreshAsync(false).ConfigureAwait(false);

        InvokeOnMainThread(() => 
        {
            doneButton = new UIBarButtonItem(UIBarButtonSystemItem.Done, (s, e) =>
            {
                PerformSegue("ListCheckpointsSegue", this);
            });

            doneButton.Enabled = false;

            CheckunitTableViewSource source = null;
            if(existingCheckunits.Any())
            {
                source = new CheckunitTableViewSource(this, existingCheckunits);
            }
            else 
            {
                source = new CheckunitTableViewSource(this);
            }

            ListCheckunitTable.Source = source;
            ListCheckunitTable.Add(refreshControl);

            loadingOverlay.Hide();

            this.SetToolbarItems(new UIBarButtonItem[] {
                  new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace) { Width = 50 }
                , doneButton
            }, false);

            this.NavigationController.ToolbarHidden = false;
        });
    }

    public override void PrepareForSegue(UIStoryboardSegue segue, NSObject sender)
    {
        if (segue.Identifier == "ListCheckpointsSegue")
        {
            var controller = segue.DestinationViewController as ListCheckpointController;

            IList<Checkunit> markedCategories = new List<Checkunit>();

            for (int i = 0; i < ListCheckunitTable.NumberOfRowsInSection(0); i++)
            {
                var cell = ListCheckunitTable.CellAt(NSIndexPath.FromItemSection(i, 0));

                if(cell != null)
                {
                    if(cell.Accessory == UITableViewCellAccessory.Checkmark)
                    {
                        var originalObject = Checkunits.Where(e => e.Id == cell.Tag).SingleOrDefault();

                        if(originalObject != null)
                        {
                            markedCategories.Add(originalObject);
                        }
                        else
                        {
                            //TODO: Handle error case!    
                        }
                    }    
                }
            }

            if (markedCategories.Any())
            {
                if (controller != null)
                {
                    if(existingAssessments.Any() && existingCheckunits.Any())
                    {
                        controller.Initialize(masterModel, markedCategories, existingAssessments, existingCheckunits);
                    }
                    else
                    {
                        controller.Initialize(masterModel, markedCategories);
                    }

                }
            }
            else
            {
                //TODO: Print out message, that there are no marked elements!
            }
        }
    }

    public void DisableDoneButton()
    {
        doneButton.Enabled = false;
    }

    public void EnableDoneButton()
    {
        doneButton.Enabled = true;
    }
}

使用的基类仅处理公共侧边栏视图。 有人知道这里出了什么问题吗?

1 个答案:

答案 0 :(得分:0)

好吧,我最终创建了一个bool Array,用于存储选中的元素。 我尝试了来自Xamarin的Github的演示应用程序,但我遇到了完全相同的问题。 这使我得出结论,认为这一定是Xamarin Bug!