2015-06-26 2 views
0

Я создаю пользовательские ячейки для своего 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; 
    } 

} 

ответ

1

Поскольку каждый раз, когда клетка собирается появиться назначать делегатов в GetCell(), вы должны также удалить их каждый раз, когда клетка собирается исчезнуть в CellDisplayingEnded()

вы должны сделать метод в MFNumberCell назвал RemoveDelegates и назовите его на CellDisplayingEnded()

+0

Ahhh, хорошая идея. Я сделаю это. –

+0

@JordanHochstetler, пожалуйста, отметьте вопрос как ответ, если он помог – iamIcarus

+0

@iamlcarus Я говорил слишком рано. Кажется, что ошибка вернулась. Может быть, это не связано с делегатами, но это то, как ячейки меняют. –

Смежные вопросы