削除イベントを処理するには、UITableViewとカスタムUITableSourceオブジェクトの両方を含むViewControllerを使用する必要があります。
その後、あなたはこのようのUITableViewからの方法によりクリックされた正しい行を取得することができます:
Foundation.NSIndexPath indexPath = tableView.IndexPathForCell(cell);
そして、あなたのデータリストと同じ時間であなたのUIから行のデータを削除します。
これは私があなたのために書いたサンプルコードで、見てみましょう:
これはViewControllerを次のとおりです。
public override void ViewDidLoad()
{
//Create a custom table source
MyTableSource mySource = new MyTableSource();
//Create a UITableView
UITableView tableView = new UITableView();
CGRect tbFrame = this.View.Bounds;
tbFrame.Y += 20;
tbFrame.Height -= 20;
tableView.Frame = tbFrame;
tableView.Source = mySource;
tableView.RowHeight = 50;
this.Add (tableView);
//Handle delete event
mySource.DeleteCell += (cell) => {
//Get the correct row
Foundation.NSIndexPath indexPath = tableView.IndexPathForCell(cell);
//Remove data from source list
mySource.RemoveAt(indexPath.Row);
//Remove selected row from UI
tableView.BeginUpdates();
tableView.DeleteRows(new Foundation.NSIndexPath[]{indexPath},UITableViewRowAnimation.Fade);
tableView.EndUpdates();
};
}
このMyTableSource.cs:
public delegate void DeleteCellHandler(UITableViewCell cell);
public event DeleteCellHandler DeleteCell;
private string CellID = "MyTableCell";
private List<string> tableItems;
public MyTableSource()
{
tableItems = new List<string>();
for (int i = 0; i < 10; i++) {
tableItems.Add ("Test Cell " + i.ToString());
}
}
public void RemoveAt(int row)
{
tableItems.RemoveAt (row);
}
#region implement from UITableViewSource
public override nint RowsInSection (UITableView tableview, nint section)
{
return tableItems.Count;
}
public override UITableViewCell GetCell (UITableView tableView, Foundation.NSIndexPath indexPath)
{
MyTableCell cell = tableView.DequeueReusableCell (CellID) as MyTableCell;
if (null == cell) {
//Init custom cell
cell = new MyTableCell (UITableViewCellStyle.Default, CellID);
//Bind delete event
cell.DeleteCell += delegate {
if(null != DeleteCell)
DeleteCell(cell);
};
}
cell.Title = tableItems [indexPath.Row];
return cell;
}
#endregion
これはMyTableCellです。cs:
public class MyTableCell : UITableViewCell
{
public delegate void DeleteCellHandler();
public event DeleteCellHandler DeleteCell;
UILabel lbTitle = new UILabel();
UIButton btnDelete = new UIButton (UIButtonType.System);
public string Title{
get{
return lbTitle.Text;
}
set{
lbTitle.Text = value;
}
}
public MyTableCell (UITableViewCellStyle style, string reuseID) : base(style,reuseID)
{
lbTitle.Text = "";
lbTitle.Frame = new CoreGraphics.CGRect (0, 0, 100, 50);
this.AddSubview (lbTitle);
btnDelete.SetTitle ("Delete", UIControlState.Normal);
btnDelete.Frame = new CoreGraphics.CGRect (120, 0, 50, 50);
this.AddSubview (btnDelete);
btnDelete.TouchUpInside += delegate {
if(null != DeleteCell)
DeleteCell();
};
}
}
ご希望の場合はお手数ですが、
アドバイスが必要な場合は、ここにメッセージを残してください。
------------------------------新--------------- ---------------------
MVCモデルによれば、Controllerレイヤー内にあるため、すべてのロジックコードをViewControllerに移動することをお勧めします。
APIを呼び出したり、ローカルデータベースからデータを読み込んだりすることによってデータを管理したい場合は、より便利になります。あなたはTableSourceであなたの削除イベントを置くことができます原因
、ちょうどコントローラからイベントを削除し、TableSourceにそれを置く、のようにする必要があります。
ViewController.cs:TableSourceで
public override void ViewDidLoad()
{
//Create a custom table source
MyTableSource mySource = new MyTableSource();
//Create a UITableView
UITableView tableView = new UITableView();
CGRect tbFrame = this.View.Bounds;
tbFrame.Y += 20;
tbFrame.Height -= 20;
tableView.Frame = tbFrame;
tableView.Source = mySource;
tableView.RowHeight = 50;
this.Add (tableView);
// //Handle delete event
// mySource.DeleteCell += (cell) => {
// //Get the correct row
// Foundation.NSIndexPath indexPath = tableView.IndexPathForCell(cell);
// //Remove data from source list
// mySource.RemoveAt(indexPath.Row);
// //Remove selected row from UI
// tableView.BeginUpdates();
// tableView.DeleteRows(new Foundation.NSIndexPath[]{indexPath},UITableViewRowAnimation.Fade);
// tableView.EndUpdates();
// };
}
。 CSは、このいずれかのようgetcellを方法を変更:
public override UITableViewCell GetCell (UITableView tableView, Foundation.NSIndexPath indexPath)
{
MyTableCell cell = tableView.DequeueReusableCell (CellID) as MyTableCell;
if (null == cell) {
//Init custom cell
cell = new MyTableCell (UITableViewCellStyle.Default, CellID);
//Bind delete event
cell.DeleteCell += delegate {
// if(null != DeleteCell)
// DeleteCell(cell);
//Get the correct row
Foundation.NSIndexPath dIndexPath = tableView.IndexPathForCell(cell);
int deleteRowIndex = dIndexPath.Row;
Console.WriteLine("deleteRowIndex = "+deleteRowIndex);
//Remove data from source list
RemoveAt(deleteRowIndex);
//Remove selected row from UI
tableView.BeginUpdates();
tableView.DeleteRows(new Foundation.NSIndexPath[]{dIndexPath},UITableViewRowAnimation.Fade);
tableView.EndUpdates();
};
}
cell.Title = tableItems [indexPath.Row];
return cell;
}
あなたが作った唯一の間違いは、あなたのカスタムセルの削除イベントハンドル内の任意のパラメータを追加するべきではないです。
テーブルからセルを削除すると、他のセルは自分のIndexPathを更新しないためです。
たとえば、3つの行があり、2番目の行を削除すると、その行が機能します。 しかし、3番目の行を削除しようとすると(2番目の行を削除するだけで2番目の行です)、3行もインデックスの境界もないという例外が発生します。このセルのIndexPathまだ2です(正しい1は1です)。
上記のように、UITableViewのメソッド "IndexPathForCell"を使用して、削除イベントハンドラのインデックスを計算する必要があります。常に正しいインデックスを取得します。
--------------------
あなたが作った間違いを約イベントのinitを削除しているセルを構成したときに私がやったように、あなたは、それを初期化する必要があります。
public override UITableViewCell GetCell (UITableView tableView, Foundation.NSIndexPath indexPath)
{
MyTableCell cell = tableView.DequeueReusableCell (CellID) as MyTableCell;
if (null == cell) {
cell = new MyTableCell (UITableViewCellStyle.Default, CellID);
//Bind delete event
cell.DeleteCell += delegate {
//Delete stuff
};
}
cell.Title = tableItems [indexPath.Row];
return cell;
}
をあなただけのあなたのようにそれを使用する場合:
if (null == cell) {
cell = new MyTableCell (UITableViewCellStyle.Default, CellID);
}
//Bind delete event
cell.DeleteCell += delegate {
//Delete stuff
};
cell.Title = tableItems [indexPath.Row];
それが結合重複が発生します問題は、あなたの表のセルが再利用されているので、あなたが/挿入/削除またはscあなたのUITableViewをロールすると、 "GetCell"メソッドがトリガーされるので、セルの削除イベントを呼び出そうとすると、複数のデリゲートが呼び出され、最初のものが動作し、少なくとも2人のデリゲートがいる場合、あなたが会いました。
効果はこのスクリーンショットのようなものです: 再現手順: 1は、テーブルビューのために新しいアイテムを追加します。 2追加したばかりの項目を削除します。 3新しいアイテムを再度追加します。 4追加したばかりの項目を削除します。
デリゲートが2人いるため、例外がスローされました。
最後に、完全なサンプルコードをGitHubにアップロードして、必要に応じてダウンロードしました。
UITalbViewManagement Sample code
こんにちは、すべての まず、あなたが答えてくれてありがとう。私はこの角度での問題を見たことがないし、実際はもっと論理的であるように見える。 しかし、私は間違いなく(Console.WriteLineによって確認された)TableSource内のDeleteCellに入っていますが、コントローラのViewDidLoad関数内のDeleteCellを決して通過しません。 理由が分かりますか? – Pictar
自分の答えを修正しました。あなたの問題を解決するはずです。@ Pictar –
削除がうまくいきました。ありがとうございました:)残っている唯一の問題はTodoの追加です。私はViewDidLoadでの追加のためのビューを作成し、正しく追加のイベントをキャッチしています。私がアプリケーションを起動してTodoを追加すると正しく表示されますが、それを削除しようとすると** dIndexPath **の周囲に** NullException **が発生します。 – Pictar