ios:UITableVIewCell扩展无法按预期工作

时间:2016-08-15 19:34:46

标签: ios uitableview xamarin xamarin.ios

我的TableView单元格有一个按钮。点击,我想扩展单元格。为了扩展我在按钮点击时更改单元格的高度并重新加载行。但是当一行被扩展然后我尝试扩展另一行时,行为不是预期的。先前展开的行关闭而不是单击的行。

此外,有时我会点击两次按钮进行展开。

public class ProgramMeasurementDetailsTableViewSource : UITableViewSource
{

    List<ProgramMeasurementDetail> mList;

    string HeaderIdentfier = "programMeasurementDetailsHeader";
    string CellIdentifier = "programMeasurementDetailsCell";
    int TAG_CHECKBOX = 61;
    int TAG_LABEL_VITAL_NAME = 62;
    int TAG_LABEL_GOAL = 63;
    int TAG_BUTTON_EDIT = 64;
    int TAG_VIEW_HEADER_COLUMN_SEPARATOR = 66;
    int TAG_VIEW_ROW_COLUMN_SEPARATOR = 65;
    List<bool> expandStatusList = new List<bool>();
    UITableView tableView;

    public ProgramMeasurementDetailsTableViewSource(List<ProgramMeasurementDetail> mList, UITableView tableView)
    {
        this.tableView = tableView;
        this.mList = mList;
        for (int i = 0; i < mList.Count; i++)
            expandStatusList.Add(false);
    }

    public override nint NumberOfSections(UITableView tableView)
    {
        return 1;
    }

    public override nint RowsInSection(UITableView tableview, nint section)
    {
        return mList.Count;
    }

    public override nfloat GetHeightForHeader(UITableView tableView, nint section)
    {
        return 32;
    }

    public override nfloat GetHeightForRow(UITableView tableView, Foundation.NSIndexPath indexPath)
    {
        if (expandStatusList[indexPath.Row])
            return 70;
        else
            return 32;
    }

    public override UITableViewCell GetCell(UITableView tableView, Foundation.NSIndexPath indexPath)
    {
        UITableViewCell cell = tableView.DequeueReusableCell(CellIdentifier);
        if (cell == null)
        {
            cell = new UITableViewCell(UITableViewCellStyle.Default, CellIdentifier);
        }
        CheckBox checkBox = (CheckBox)cell.ViewWithTag(TAG_CHECKBOX);
        UILabel vitalNameLabel = (UILabel)cell.ViewWithTag(TAG_LABEL_VITAL_NAME);
        UILabel goalLabel = (UILabel)cell.ViewWithTag(TAG_LABEL_GOAL);
        UIButton editGoalButton = (UIButton)cell.ViewWithTag(TAG_BUTTON_EDIT);
        editGoalButton.TouchUpInside += (object sender, EventArgs e) =>
         {
             expandStatusList[indexPath.Row] = !expandStatusList[indexPath.Row];
             tableView.ReloadRows(new Foundation.NSIndexPath[] { indexPath }, UITableViewRowAnimation.Automatic);

         };

        .....
        return cell;
    }
}

我尝试在if(cell == null)中移动按钮单击事件处理,然后按钮单击/展开根本不起作用。我放了断点,似乎部分永远不会被执行。

我在故事板中设计了单元格布局。

我已经在这个问题上挣扎了很长一段时间了。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:2)

当您向上和向下滚动列表时,您看到的错误是否会发生?这种情况正在发生,因为您正在使用TouchUpInside方法中的GetCell事件处理程序进行连接,然后在重用该单元格时它永远不会脱钩,因此您最终会将多个单元连接到同一个处理程序甚至多个处理程序!

通常,您不希望在GetCell方法中对事物执行这些类型,它只应用于DequeueReusableCell或创建新类型。其他一切都应该在自定义单元格内完成。

查看您的代码示例,看起来您使用的是自定义单元格,所以您可以这样做:

1。)在GetCell中,将按钮的标记设置为IndexPath的行

editGoalButton.Tag = indexPath.Row;

2。)在ProgramMeasurementDetailsTableViewSource中为事件处理程序创建一个单独的方法:

private void ToggleRow(object sender, EventArgs e)
{
    var btn = sender as UIButton;
    expandStatusList[btn.Tag] = !expandStatusList[btn.Tag];
    tableView.ReloadRows(new Foundation.NSIndexPath[] { NSIndexPath.FromRowSection(btn.Tag, 0) }, UITableViewRowAnimation.Automatic);
}

3。)在GetCell取消挂钩TouchUpInside处理程序之前取消隐藏:

editGoalButton.TouchUpInside -= ToggleRow;
editGoalButton.TouchUpInside += ToggleRow;

虽然这样可以确保按钮只挂了一次,但这并不是处理这种情况的正确方法。您应该使用自定义单元格并在单元格中进行所有连线,然后在PrepareForReuse中的UITableViewCell覆盖中取消挂钩并进行清理。我强烈推荐这个Xamarin tutorial

如果您确实经历过这个问题,请注意GetCell方法的整合程度。

<强> - UPDATE - CustomCell课程中:

private EventHandler _tapAction;
public void Setup(EventHandler tapAction, int row, ....)
{
     //keep a reference to the action, so we can unhook it later
     _tapAction = tapAction;
     editGoalButton.Tag = row;
     ....
     editGoalButton.TouchUpInside += _tapAction;
}

public override void PrepareForReuse()
{
     ....
     editGoalButton.TouchUpInside -= _tapAction;
     _tapAction = null;
}

当您在ToggleRow中调用Setup时,您只需将GetCell方法作为Action参数传递。