Я создаю пользовательские ячейки для своего TableView. У меня 8 различных типов клеток. Это происходит для всех ячеек, но я выберу один для этого примера, чтобы продемонстрировать, что происходит. У моей ячейки NumberCell есть TextField. Ниже вы можете увидеть, как я настраиваю ячейку с помощью GetCell и SetupDelegates. Все работает нормально, пока у меня не будет достаточно ячеек на экране, которые вы должны начать прокручивать, чтобы создавать новые ячейки того же типа (которые деактивируют и повторно используют старые ячейки). Ну, похоже, что моя ячейка меняет answerNumberField.Text, когда я прокручиваю их с экрана, а затем снова и, возможно, что-то связано с отправкой formItem в пользовательскую ячейку, но я не уверен. Наверное, мне хотелось бы знать, правильно ли это настроить мои делегаты внутри моей настраиваемой ячейки. Вы можете видеть причину, по которой я это сделал, чтобы я мог получить доступ к информации formItem, находясь в ячейке, но это может быть причиной этой проблемы. Я также сделал это, чтобы попытаться отделить логику, чтобы мой GetCell не стал огромным. Любая помощь будет высоко оценена, и если вам нужно больше информации, просто спросите. Благодаря!Пользовательский Xib UITableViewCell с UITextField: проблемы с делегатами и Dequequing
Регистрация файла XIb пользовательского элемента ячейки:
TableView.RegisterNibForCellReuse (MFNumberCell.Nib, MFNumberCell.Key);
GetCell
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
var cell = new UITableViewCell();
FormItem formItem = formItems [indexPath.Row];
switch (formItem.type) {
case "MFNumber":
var numberCell = (MFNumberCell)tableView.DequeueReusableCell (MFNumberCell.Key, indexPath);
numberCell.SetupDelegates (formItem, detailVC);
cell = numberCell;
break;
...
}
//Remove inset edge constraints
cell.SeparatorInset = UIEdgeInsets.Zero;
cell.LayoutMargins = UIEdgeInsets.Zero;
//Don't show background highlight when selecting the cell
cell.SelectionStyle = UITableViewCellSelectionStyle.None;
return cell;
}
Пользовательские NumberCell
public void SetupDelegates (FormItem formItem, DetailViewController detailVC)
{
validationView.Layer.MasksToBounds = false;
validationView.Layer.CornerRadius = 13;
//Adds left space before text
answerNumberField.LeftViewMode = UITextFieldViewMode.Always;
if (answerNumberField.LeftView == null) {
UIView leftView = new UIView (new CGRect (0, 0, 15, 25));
answerNumberField.LeftView = leftView;
}
if (!String.IsNullOrWhiteSpace (formItem.answer)) {
answerNumberField.Text = formItem.answer;
} else {
answerNumberField.Text = "";
}
answerNumberField.Placeholder = formItem.placeholder;
answerNumberField.KeyboardType = UIKeyboardType.NumberPad;
questionTextView.Text = formItem.question_text;
UtilHelper.UpdateValidationView(formItem, validationView);
helpButton.TouchUpInside += (object sender, EventArgs e) => {
var okAlertController = UIAlertController.Create ("Help", formItem.help, UIAlertControllerStyle.Alert);
okAlertController.AddAction (UIAlertAction.Create ("OK", UIAlertActionStyle.Default, null));
detailVC.PresentViewController (okAlertController, true, null);
};
answerNumberField.ShouldChangeCharacters += (UITextField tf, NSRange range, string replacementText) => {
string next_answer = tf.Text + replacementText;
bool isMatch = Regex.IsMatch(next_answer, formItem.input_constraint);
if(isMatch){
formItem.answer = next_answer;
}
UtilHelper.UpdateValidationView(formItem, validationView);
return isMatch;
};
answerNumberField.Ended += (object sender, EventArgs e) => {
if (String.IsNullOrWhiteSpace(answerNumberField.Text)) {
formItem.answer = "";
}else{
formItem.answer = answerNumberField.Text;
}
FormGenerator.updateFormItemInSQLiteDatabase (formItem);
UtilHelper.UpdateValidationView(formItem, validationView);
};
}
Вот Решение, которое сработало для меня
Создайте EventHandlers и сохраните их в ячейке, чтобы вы могли вызвать метод Remove в методе CellDisplayingEnded вашего TableViewSource.
public partial class MFNumberCell : UITableViewCell
{
public static readonly UINib Nib = UINib.FromName ("MFNumberCell", NSBundle.MainBundle);
public static readonly NSString Key = new NSString ("MFNumberCell");
public EventHandler helpButtonClick;
public UITextFieldChange answerFieldShouldChangeChar;
public EventHandler answerFieldEnded;
public MFNumberCell (IntPtr handle) : base (handle)
{
}
public static MFNumberCell Create()
{
return (MFNumberCell)Nib.Instantiate (null, null) [0];
}
public void Update (FormItem formItem, DetailViewController detailVC)
{
validationView.Layer.MasksToBounds = false;
validationView.Layer.CornerRadius = 13;
//Adds left space before text
answerNumberField.LeftViewMode = UITextFieldViewMode.Always;
if (answerNumberField.LeftView == null) {
UIView leftView = new UIView (new CGRect (0, 0, 15, 25));
answerNumberField.LeftView = leftView;
}
if (!String.IsNullOrWhiteSpace (formItem.answer)) {
answerNumberField.Text = formItem.answer;
} else {
answerNumberField.Text = "";
}
answerNumberField.Placeholder = formItem.placeholder;
answerNumberField.KeyboardType = UIKeyboardType.NumberPad;
questionTextView.Text = formItem.question_text;
UtilHelper.UpdateValidationView(formItem, validationView);
// HELP BUTTON START //
helpButtonClick = (s, e) => {
var okAlertController = UIAlertController.Create ("Help", formItem.help, UIAlertControllerStyle.Alert);
okAlertController.AddAction (UIAlertAction.Create ("OK", UIAlertActionStyle.Default, null));
detailVC.PresentViewController (okAlertController, true, null);
};
helpButton.TouchUpInside += helpButtonClick;
// HELP BUTTON END //
// ANSWER TEXT FIELD START //
answerFieldShouldChangeChar = (UITextField tf, NSRange range, string replacementText) => {
string next_answer = tf.Text + replacementText;
bool isMatch = Regex.IsMatch(next_answer, formItem.input_constraint);
if(isMatch){
formItem.answer = next_answer;
}
UtilHelper.UpdateValidationView(formItem, validationView);
return isMatch;
};
answerNumberField.ShouldChangeCharacters += (UITextFieldChange)answerFieldShouldChangeChar;
answerFieldEnded = (s, e) => {
if (String.IsNullOrWhiteSpace (answerNumberField.Text)) {
formItem.answer = "";
} else {
formItem.answer = answerNumberField.Text;
}
FormGenerator.updateFormItemInSQLiteDatabase (formItem);
UtilHelper.UpdateValidationView (formItem, validationView);
};
answerNumberField.Ended += answerFieldEnded;
// ANSWER TEXT FIELD END //
}
public void RemoveDelegates(){
answerNumberField.Ended -= answerFieldEnded;
answerNumberField.ShouldChangeCharacters -= answerFieldShouldChangeChar;
helpButton.TouchUpInside -= helpButtonClick;
}
}
Ahhh, хорошая идея. Я сделаю это. –
@JordanHochstetler, пожалуйста, отметьте вопрос как ответ, если он помог – iamIcarus
@iamlcarus Я говорил слишком рано. Кажется, что ошибка вернулась. Может быть, это не связано с делегатами, но это то, как ячейки меняют. –