TableView单元在滚动时重置数据

时间:2015-07-14 12:15:21

标签: c# ios uitableview xamarin

----- ----- EDIT

通过在TableViewSource中使用DraggingStarted方法,我找到了解决问题的方法。它不是最优化的解决方案,我将继续寻找一种正确的方法来处理我的问题,但是现在,我可以继续我的流程。

public override void DraggingStarted(UIScrollView scrollView)
{
    for (int i = 0; i < 12; i++)
    {
        try
        {
            GlobalSupport.NewClientData[i] = ((scrollView as UITableView).CellAt(NSIndexPath.FromItemSection(i, 0)).ContentView.Subviews[1] as UITextField).Text;
        }
        catch
        {
        }
    }

    Console.WriteLine("hoi");
}

在我的GetCell方法中,然后我搜索这个新的数据结构,找到正确的值:

if (GlobalSupport.NewClientData[indexPath.Row] != "")
{
    cell.cellValue = GlobalSupport.NewClientData[indexPath.Row];
}

----- ----- EndEdit中

我正在开发一个专注于TableView的应用程序。这意味着我的大多数屏幕都是TableView,其中包含可重复使用的单元格。这些单元格是使用Xcode Designer定义的(这意味着我的资源中每个不同的唯一单元格都有.cs,.xib和.designer。)

在使用预定义数据(自定义数据对象,词典,列表等)构建TableView时,我调用单元格.cs中的方法来修改.xib中定义的两个UILabel(或UILabel和UIImageView)。 。一切顺利;提供的数据通过我的TableViewSource中的GetCell方法放入标签和其他控件中,并保留在那里,即使在滚动之后(因为数据是预定义的,并使用IndexPath.Row来确定放置的位置)。

现在遇到了麻烦:

我有另一个单元格,里面有UILabel和UITextField。 UILabel的文本已修改为与我的可本地化字符串文件相对应。我在我的TableViewSource中的GetCell方法中有一个开关,如下所示:

public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
    CTextInput cell = (CTextInput)tableView.DequeueReusableCell(CTextInput.Identifier);

    switch (indexPath.Row)
    {
        case 0:
            cell.cellLabel = NSBundle.MainBundle.LocalizedString("txtBSN", "", "");
            break;
        case 1:
            cell.cellLabel = NSBundle.MainBundle.LocalizedString("txtPrefix", "", "");
            break;
        case 2:
            cell.cellLabel = NSBundle.MainBundle.LocalizedString("txtInitials", "", "");
            break;
        case 3:
            cell.cellLabel = NSBundle.MainBundle.LocalizedString("txtFirstName", "", "");
            break;
        case 4:
            cell.cellLabel = NSBundle.MainBundle.LocalizedString("txtLastName", "", "");
            break;
        case 5:
            cell.cellLabel = NSBundle.MainBundle.LocalizedString("txtDateOfBirth", "", "");
            cell.Accessory = UITableViewCellAccessory.DetailDisclosureButton;
            break;
        case 6:
            cell.cellLabel = NSBundle.MainBundle.LocalizedString("txtCity", "", "");
            break;
        case 7:
            cell.cellLabel = NSBundle.MainBundle.LocalizedString("txtStreet", "", "");
            break;
        case 8:
            cell.cellLabel = NSBundle.MainBundle.LocalizedString("txtHouseNumber", "", "");
            break;
        case 9:
            cell.cellLabel = NSBundle.MainBundle.LocalizedString("txtZipcode", "", "");
            break;
        case 10:
            cell.cellLabel = NSBundle.MainBundle.LocalizedString("txtCountry", "", "");
            break;
        case 11:
            cell.cellLabel = NSBundle.MainBundle.LocalizedString("txtPhonenumber", "", "");
            break;
        default:
            break;
    }

    return cell;
}

这很有效。

现在,当加载视图时,用户可以在UITextField中输入他或她的数据,在每个UILabel旁边。提供数据,当用户沿着TableView向下移动时,所有文本都停留在那里......直到用户到达屏幕的底部,并且需要滚动才能查看其他单元格。接下来会发生的是,前几个单元格的UITextField中提供的数据被重置为单元格的.xib文件中指定的值,即“”。这是因为我的GetCell方法开头的DequeueReusableCell。每当新单元格进入用户视图时,都会调用GetCell方法。这意味着从用户视图中消失的所有单元格将重置为默认值。

Supply the data

Scrolling down

Scrolling back up

我不想为此视图中的每个单元格分别设置一组.cs,.xib和.designer文件,并且还没有找到保存单元格UITextField内容的方法。 更重要的是,我需要在每个单元格内部使用UITextField的内容,以便创建一个新对象,我需要进一步推进这个过程。

非常感谢有关此主题的任何帮助。如果您需要更多信息,请随时与我联系!

亲爱的问候, 的Björn

1 个答案:

答案 0 :(得分:1)

UITableView的DataSource需要为单元格提供完全正确呈现所需的任何数据。由于细胞被重复使用,它们可以被认为是“愚蠢的”#34;并完全依赖数据源来了解要显示的内容。

记住这一点,您需要做的是更新您的DataSource以包含输入到单元格的UITextField中的任何内容。

以下是如何完成此任务的示例:

1.。)将UITableView的数据源实现为键/值对:

DataSource = new Dictionary<string, string> () {
    { "Label 1", string.Empty },
    { "Label 2", string.Empty },
    ...
    ...
};

针对您的场景&#34;标签1&#34;将是NSBundle.MainBundle.LocalizedString("txtBSN", "", "")

2.。)像这样实施您的CTextInput单元格:

public partial class CTextInput : UITableViewCell
{
    Action<string, string> OnTextFieldTextChanged;

    public CustomCell ()
    {
    }

    public CustomCell (IntPtr handle) : base (handle)
    {
    }

    public void SetupCell (string labelText, string value, Action<string, string> onTextFieldTextChanged)
    {
        CellLabel.Text = labelText;
        CellTextField.Text = value;
        OnTextFieldTextChanged = onTextFieldTextChanged;

        CellTextField.EditingDidEnd += HandleEditingDidEnd;
    }

    void HandleEditingDidEnd (object sender, EventArgs e)
    {
        var textField = sender as UITextField;
        OnTextFieldTextChanged (CellLabel.Text, textField.Text);
    }

    // clean up
    public override void PrepareForReuse ()
    {
        base.PrepareForReuse ();

        OnTextFieldTextChanged = null;
        CellTextField.EditingDidEnd -= HandleEditingDidEnd;
    }

    protected override void Dispose (bool disposing)
    {
        if (disposing) {
            OnTextFieldTextChanged = null;
        }

        base.Dispose (disposing);

    }

}

这里重要的是SetupCell方法和HandleEditingDidEnd事件处理程序。您挂钩到UITextField的EditingDidEnd,以便您可以调用传入的onTextFieldTextChanged操作。

3。)添加OnTextFieldTextChange处理程序并在View Controller中实现GetCell方法,如下所示:

public override UITableViewCell GetCell (UITableView tableView, Foundation.NSIndexPath indexPath)
{
    var cell = tableView.DequeueReusableCell ("CellIdentifier")  as CTextInput ?? new CTextInput ();

    var labelText = DataSource.Keys.ElementAt (indexPath.Row);
    var textFieldText = DataSource.Values.ElementAt (indexPath.Row);

    cell.SetupCell (labelText, textFieldText, OnTextFieldTextChange);

    return cell;
}


public void OnTextFieldTextChange (string key, string value)
{
    if (DataSource.ContainsKey (key)) {
        DataSource [key] = value;
    }
}

在这里,您可以定义OnTextFieldTextChange方法,该方法可以传入Action<string, string> onTextFieldTextChanged类中先前定义的SetupCell方法中的CTextInput参数。

OnTextFieldTextChange方法中,您只需更新DataSource中给定键的值。

现在,当UITextField发出EditingDidEnd事件时,数据源将更新为包含用户输入的值。

希望这有帮助!