使用UITextField的自定义Xib UITableViewCell:代理和Dequequing的麻烦

时间:2015-06-26 01:46:20

标签: ios uitableview xamarin xamarin.ios

我正在为TableView创建自定义单元格。我有8种不同的细胞。所有单元格都会发生这种情况,但我会为此示例选择一个来演示正在发生的事情。我的单元格NumberCell中有一个TextField。下面你可以看到我如何使用GetCell和SetupDelegates设置单元格。一切正常,直到我在屏幕上有足够的单元格,您必须开始滚动以创建相同类型的新单元格(出列并重新使用旧单元格)。好吧,当我将它们从屏幕上滚动然后重新开启时,我的单元格似乎正在交换answerNumberField.Text,这可能与将formItem发送到自定义单元格有关,但我不确定。我想我想知道这是否是在我的自定义单元格中设置我的委托的正确方法。您可以看到我所做的原因是为了在单元格中可以访问formItem信息,但这可能是造成问题的原因。我也尝试将逻辑分开,以便我的GetCell不会变大。任何帮助将不胜感激,如果您需要更多信息,请询问。谢谢!

注册自定义单元格的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并将它们保存到单元格中,以便可以在TableViewSource的CellDisplayingEnded方法中调用Remove方法。

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 个答案:

答案 0 :(得分:1)

由于每次出现单元格时都要在GetCell()中指定Delegates,所以每次单元格即将消失时,你也应该删除它们在CellDisplayingEnded()中

你应该在名为RemoveDelegates的MFNumberCell中执行一个方法 并在CellDisplayingEnded()

上调用它