2013-09-30 41 views
2

我想在iOS中使用Xamarin和MvvmCross創建可擴展列表視圖。iOS:可擴展列表視圖不繪製新添加的控件

這個場景是我有一個列表視圖,當列表視圖中的一行被選中時,它展開(動畫)以顯示一個集合視圖,通過lazyloading加載。

下面是代碼我迄今爲止:

適配器:

public class MercatoAnimatedExpandableTableSource : MvxTableViewSource 
{ 
    private readonly string _key; 
    private readonly List<object> items; 
    private Dictionary<object, bool> expandableState = new Dictionary<object, bool>(); 

    public MercatoAnimatedExpandableTableSource(UITableView tableView, IEnumerable<object> items, UINib nib, string key) 
     : base(tableView) 
    { 
     _key = key; 
     this.items = items.ToList(); 
     this.items.ForEach(x => expandableState[x] = true); 
     tableView.RegisterNibForCellReuse(nib, key); 
    } 

    protected override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item) 
    { 
     var cell = tableView.DequeueReusableCell(_key); 

     cell.Frame = new RectangleF(cell.Frame.X, cell.Frame.Y, cell.Frame.Width, GetHeightForRow(tableView, indexPath)); 

     return cell; 
    } 

    public override void RowSelected(UITableView tableView, NSIndexPath indexPath) 
    { 
     base.RowSelected(tableView, indexPath); 

     var isExpanded = expandableState[items[indexPath.Row]]; 

     expandableState[items[indexPath.Row]] = !isExpanded; 

     var row = this.GetCell(tableView, indexPath); 

     (row as FamilysubgroupViewCell).ExpandCells(); 

     tableView.ReloadRows(new[] { indexPath }, UITableViewRowAnimation.Automatic); 
    } 

    public override float GetHeightForRow(UITableView tableView, NSIndexPath indexPath) 
    { 
     var isExpanded = expandableState[items[indexPath.Row]]; 
     if (isExpanded) 
     { 
      return 25; 
     } 

     return 400; 
    } 

    protected override object GetItemAt(NSIndexPath indexPath) 
    { 
     return items[indexPath.Row]; 
    } 
} 

細胞:

public FamilySubgroupViewCell (IntPtr handle) : base (handle) 
    { 
     this.DelayBind(() => 
     { 
      this.FamilyCollectionViewContainer.BackgroundColor = UIColor.Blue; 
      var bindingset = this.CreateBindingSet<FamilySubgroupViewCell, FamilySubTypeViewModel>(); 
      bindingset.Bind(this.FamilyGroupTitleLabel).To(x => x.FamilySubType.FamilySubGroupDescription); 
      bindingset.Bind(this.FamilyGroupDescLabel).To(x => x.FamilySubType.FamilySubGroupDetail); 
      bindingset.Apply(); 
     }); 

    } 

    public void ExpandCells(Action onUpdate) 
    { 
     var context = this.DataContext as FamilySubTypeViewModel; 
     context.PopulateAndRun(() => 
     { 
      Debug.WriteLine("Populating Models complete : now showing cells"); 
      var collection = new FamilySubGroupModelsCollection(); 
      collection.ViewModel = context; 
      Debug.WriteLine("FamilySubGroupCell : Showing {0} Items", context.FamilyModels.Count); 

      this.FamilyCollectionViewContainer.Add(collection.View); 

      if (onUpdate != null) onUpdate(); 
     }); 
    } 

問題

所以當一個單元格被選中時,它會翻轉'isExpanded'屬性,使其具有新的高度 - 工作正常。然後,單元會發送一條消息來'擴展'單元,然後加載一個新的集合並將其添加到視圖中(通過View出口)。

但是,該集合絕不會在視圖上重新呈現。它填充良好,添加到視圖中,但它在新擴展的單元格上實際上永遠不可見。如果我在DelayBind()方法中初始創建單元格時加載它(即 - 沒有延遲加載),那麼它工作正常。

是否嘗試過類似的事情重繪細胞

this.Draw(this.Bounds); 

後的集合被添加到視圖,但無濟於事。

我在做什麼錯?

回答

1

的代碼塊感覺像它可能會造成混亂顯示器:

var row = this.GetCell(tableView, indexPath); 
    (row as FamilysubgroupViewCell).ExpandCells(); 
    tableView.ReloadRows(new[] { indexPath }, UITableViewRowAnimation.Automatic); 

這樣做是:

  • 獲取當前單元格,並告訴它擴大
  • 然後問表來重新加載行(在這一點可能使用不同的單元實例)。

我還擔心行:

var context = this.DataContext as FamilySubTypeViewModel; 

將連接你的細胞子顯示爲當前視圖模型 - 如果電池被重複使用,這將不更新(賦予了新的視圖模型)。

解決這兩個問題,一個快速的(只有輕度污染)的方式是改變倍率爲GetOrCreateCellFor喜歡的東西:

protected override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item) 
{ 
    var cell = tableView.DequeueReusableCell(_key); 

    cell.Frame = new RectangleF(cell.Frame.X, cell.Frame.Y, cell.Frame.Width, GetHeightForRow(tableView, indexPath)); 

    ((MyCellType)cell).ShowExpandedState(expandableState[items[indexPath.Row]]); 

    return cell; 
} 

ShowExpandedState(bool)將能夠重複使用後重置電池的擴展區域的。


其他選項:

  • 取而代之的是,你可以簡單地返回不同的細胞類型,擴大對非擴展行?
  • 或者您可以將展開/未展開的信息放入Cell的ViewModel,以便它可以將數據綁定到擴展狀態並更新它自己的佈局? (你仍然需要一些機制來告訴表格有關尺寸變化雖然)

在:

this.Draw(this.Bounds); 

我不是太驚訝並沒有工作 - 通常你必須鼓勵系統重新繪製視圖 - 使用諸如SetNeedsDisplay之類的東西(並且有時也在孩子更改後SetNeedsLayout之後)

+0

您在第一次觀察時發現了。 tableView.ReloadRows()實例化了一個新的單元,它沒有展開的集合視圖。將您在GetOrCreateCellFor中建議的代碼放在一邊。謝謝! –