菜鸟教程小白 发表于 2022-12-12 21:44:41

ios:UITableVIewCell 扩展未按预期工作


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

<p>另外,有时我必须单击按钮两次才能展开。 </p>

<pre><code>public class ProgramMeasurementDetailsTableViewSource : UITableViewSource
{

    List&lt;ProgramMeasurementDetail&gt; mList;

    string HeaderIdentfier = &#34;programMeasurementDetailsHeader&#34;;
    string CellIdentifier = &#34;programMeasurementDetailsCell&#34;;
    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&lt;bool&gt; expandStatusList = new List&lt;bool&gt;();
    UITableView tableView;

    public ProgramMeasurementDetailsTableViewSource(List&lt;ProgramMeasurementDetail&gt; mList, UITableView tableView)
    {
      this.tableView = tableView;
      this.mList = mList;
      for (int i = 0; i &lt; 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)
            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) =&gt;
         {
             expandStatusList = !expandStatusList;
             tableView.ReloadRows(new Foundation.NSIndexPath[] { indexPath }, UITableViewRowAnimation.Automatic);

         };

      .....
      return cell;
    }
}
</code></pre>

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

<p>我在 Storyboard中设计了单元格布局。 </p>

<p>我已经为这个问题苦苦挣扎了一段时间了。任何帮助表示赞赏。</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>当您上下滚动列表时,您看到的错误是否会发生?发生这种情况是因为您在 <code>GetCell</code> 方法中连接了 <code>TouchUpInside</code> 事件处理程序,然后在重用单元格时它永远不会脱钩,因此您最终会连接多个单元格到同一个处理程序甚至多个处理程序!</p>

<p>一般来说,你不想在 <code>GetCell</code> 方法中对事物做这些类型,它应该只用于 <code>DequeueReusableCell</code> 或创建一个新的。其他一切都应在自定义单元格中完成。 </p>

<p>查看您的代码示例,您似乎没有使用自定义单元格,所以您可以这样做:</p>

<p>1.) 在<code>GetCell</code>中设置按钮的标签为IndexPath的行</p>

<pre><code>editGoalButton.Tag = indexPath.Row;
</code></pre>

<p>2.) 在 <code>ProgramMeasurementDetailsTableViewSource</code> 中为您的事件处理程序创建一个单独的方法:</p>

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

<p>3.) 在 <code>GetCell</code> 中,在重新 Hook<code>TouchUpInside</code> 处理程序之前取消 Hook :</p>

<pre><code>editGoalButton.TouchUpInside -= ToggleRow;
editGoalButton.TouchUpInside += ToggleRow;
</code></pre>

<p>虽然这将确保按钮只连接一次,但它确实不是处理此类情况的正确方法。您应该使用自定义单元格并在单元格中进行所有接线,然后在 <code>UITableViewCell</code> 中的 <code>PrepareForReuse</code> 覆盖中取消 Hook 和清理。我强烈建议通过这个 <a href="https://developer.xamarin.com/guides/ios/user_interface/tables/part_3_-_customizing_a_table&#39;s_appearance/" rel="noreferrer noopener nofollow">Xamarin tutorial</a> </p>

<p>如果您确实通过了...请注意 <code>GetCell</code> 方法的整合程度。</p>

<p><strong>--更新--</strong>
在您的 <code>CustomCell</code> 类中:</p>

<pre><code>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;
}
</code></pre>

<p>当您在 <code>GetCell</code> 中调用 <code>Setup</code> 时,您只需通过 <code>ToggleRow</code> 方法作为 Action 参数。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios:UITableVIewCell 扩展未按预期工作,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/38961804/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/38961804/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios:UITableVIewCell 扩展未按预期工作