我正在使用Xamarin.iOS.In TableView.我用Button绑定了Cell.
对于Button Click我正在通过以下代码进行订阅和取消订阅Cell事件
cell.btn_Click.Tag = indexPath.Row; cell.btn_Click.TouchUpInside -= BtnClickEvent; cell.btn_Click.TouchUpInside += BtnClickEvent;
当我再次调用数据api并设置为TableView时,这不能正常工作.
说明:
当我打开ViewController第一次单元格按钮时单击事件触发1次.然后我第二次打开它会点击2次单击按钮事件.我使用高级代码进行订阅和取消订阅按钮事件,然后为什么它会多次调用.
我在iOS 11.2中遇到的这个问题
第一种方式:
源类完整代码
class StockListSourceClass : UITableViewSource { private List<PacketAndPacketDetailItem> stockLists; private List<string> serialNoList; private UINavigationController navigationController; public static event EventHandler BtnClickEvented; public StockListSourceClass(List<PacketAndPacketDetailItem> stockLists,List<string> serialNolist,UINavigationController navigationController) { this.stockLists = stockLists; this.serialNoList = serialNolist; this.navigationController = navigationController; } public override UITableViewCell GetCell(UITableView tableView,NSIndexPath indexPath) { StockTableViewCell cell = tableView.DequeueReusableCell(StockTableViewCell.Key) as StockTableViewCell ?? StockTableViewCell.Create(); var item = stockLists[indexPath.Row]; if (serialNoList.Contains(item.SerialNo)) cell.BindData(item,true); else cell.BindData(item,false); cell.SelectionStyle = UITableViewCellSelectionStyle.None; cell.PreservesSuperviewLayoutMargins = false; cell.SeparatorInset = UIEdgeInsets.Zero; cell.LayoutMargins = UIEdgeInsets.Zero; cell.SetNeedsLayout(); cell.LayoutIfNeeded(); cell.btn_Click.Tag = indexPath.Row; cell.btn_Click.TouchUpInside -= BtnClickEvent; cell.btn_Click.TouchUpInside += BtnClickEvent; cell.btn_Click.TouchUpInside += (sender,e) => { var imageName = ((UIButton)sender).TitleLabel.Text; if (imageName.Equals("unchecked")) { ((UIButton)sender).SetBackgroundImage(UIImage.FromBundle("checked"),UIControlState.Normal); ((UIButton)sender).TitleLabel.Text = "checked"; } else { ((UIButton)sender).SetBackgroundImage(UIImage.FromBundle("unchecked"),UIControlState.Normal); ((UIButton)sender).TitleLabel.Text = "unchecked"; } }; return cell; } public void BtnClickEvent(object sender,EventArgs e) { var row = ((UIButton)sender).Tag; MarketSheetViewController.RowNo = (int)row; if (BtnClickEvented != null) { BtnClickEvented(stockLists[(int)row].SerialNo,EventArgs.Empty); } } public override nint RowsInSection(UITableView tableview,nint section) { return stockLists.Count; } public override void RowSelected(UITableView tableView,NSIndexPath indexPath) { var storyboard = UIStoryboard.FromName("Main",null); var webController = storyboard.InstantiateViewController("PacketDetailViewController") as PacketDetailViewController; webController.item = stockLists[indexPath.Row]; this.navigationController.PushViewController(webController,true); } }
在ViewController里面我用它
StockListSourceClass.BtnClickEvented += (sender,e) => { if (!(serialNoList.Contains(stockLists[RowNo].SerialNo))) serialNoList.Add(stockLists[RowNo].SerialNo); else serialNoList.Remove(stockLists[RowNo].SerialNo); SetUpperPanelData(); };
第二种方式
cell.btn_Click.TouchUpInside += (sender,e) => { var imageName = ((UIButton)sender).TitleLabel.Text; if (imageName.Equals("unchecked")) { ((UIButton)sender).SetBackgroundImage(UIImage.FromBundle("checked"),UIControlState.Normal); ((UIButton)sender).TitleLabel.Text = "checked"; } else { ((UIButton)sender).SetBackgroundImage(UIImage.FromBundle("unchecked"),UIControlState.Normal); ((UIButton)sender).TitleLabel.Text = "unchecked"; } var row = ((UIButton)sender).Tag; MarketSheetViewController.RowNo = (int)row; if (BtnClickEvented != null) { BtnClickEvented(stockLists[(int)row].SerialNo,EventArgs.Empty); } };
解决方法
最后通过以下方式得到解决方案
StockTableViewCell.cs
public partial class StockTableViewCell : UITableViewCell { public int Row; public event EventHandler<int> SelectButtonTapped; public void BindData(PacketAndPacketDetailItem item,bool flag,int row) { this.Row = row; btn_click.TouchUpInside -= OnSelectButtonTapped; btn_click.TouchUpInside += OnSelectButtonTapped; } private void OnSelectButtonTapped(object sender,EventArgs e) { if (SelectButtonTapped != null) SelectButtonTapped(sender,Row); } }
TableSource类
class StockListSourceClass : UITableViewSource { public event EventHandler<int> SelectButtonTapped; public override UITableViewCell GetCell(UITableView tableView,NSIndexPath indexPath) { StockTableViewCell cell = tableView.DequeueReusableCell(StockTableViewCell.Key) as StockTableViewCell ?? StockTableViewCell.Create(); var item = stockLists[indexPath.Row]; if (serialNoList.Contains(item.SerialNo)) cell.BindData(item,true,indexPath.Row); else cell.BindData(item,false,indexPath.Row); cell.SelectButtonTapped -= OnCellSpeakButtonTapped; cell.SelectButtonTapped += OnCellSpeakButtonTapped; cell.SelectionStyle = UITableViewCellSelectionStyle.None; cell.PreservesSuperviewLayoutMargins = false; cell.SeparatorInset = UIEdgeInsets.Zero; cell.LayoutMargins = UIEdgeInsets.Zero; cell.SetNeedsLayout(); cell.LayoutIfNeeded(); return cell; } void OnCellSpeakButtonTapped(object sender,int e) { var row = e; MarketSheetViewController.RowNo = (int)row; if (SelectButtonTapped != null) SelectButtonTapped(sender,e); } }
最后我们可以在ViewController中获取Cell按钮的单个事件
定义这种方式
stockListSourceClass.SelectButtonTapped -= OnSelectButtonTapped; stockListSourceClass.SelectButtonTapped += OnSelectButtonTapped;
并实施它.
private void OnSelectButtonTapped(object sender,int e) { if (!(serialNoList.Contains(stockLists[RowNo].SerialNo))) serialNoList.Add(stockLists[RowNo].SerialNo); else serialNoList.Remove(stockLists[RowNo].SerialNo); SetUpperPanelData(); }