2010-09-02 99 views
1

我有一個TabControl,可以通過拖放標籤來重新排列。當前進程從列表中刪除一個項目並將其添加到新的位置。由於選項卡有多複雜,我在切換選項卡時遇到了一些性能問題,因此找到了一種替代方法,它可以存儲呈現的選項卡並在請求時重新加載它們。我唯一的問題是,拖放標籤時,它會重新渲染每個標籤並導致相同的延遲。有沒有辦法簡單地移動集合中的項目而不是添加/刪除它?重新排列集合而不添加/刪除項目?

或者失敗,有沒有辦法在拖放操作過程中取消OnItemsChanged事件中的添加/刪除操作?該過程會影響控件的視覺效果,所以如果是由拖放操作引起的,我需要實際取消添加/刪除事件(用戶也可以正常添加/刪除標籤)。

回答

0

我最終修改了我的OnItemsChanged事件,以便以更低的調度程序優先級和添加代碼運行Remove代碼,因此它使Add操作有機會取消刪除並重用TabItem的ContentPresenter而不是渲染新代碼。

原始代碼,我開始從here

它基本上存儲的TabItem ContentPresenters所以切換標籤時,它使用的不是重繪一個新的存儲ContentPresenter獲得。下面是我對OnItemsChanged就該好好拖動修改/刪除重用,而不是重繪新

case NotifyCollectionChangedAction.Add: 
case NotifyCollectionChangedAction.Remove: 

    // Search for recently deleted items caused by a Drag/Drop operation 
    if (e.NewItems != null && _deletedObject != null) 
    { 
     foreach (var item in e.NewItems) 
     { 
      if (_deletedObject == item) 
      { 
       // If the new item is the same as the recently deleted one (i.e. a drag/drop event) 
       // then cancel the deletion and reuse the ContentPresenter so it doesn't have to be 
       // redrawn. We do need to link the presenter to the new item though (using the Tag) 
       ContentPresenter cp = FindChildContentPresenter(_deletedObject); 
       if (cp != null) 
       { 
        int index = _itemsHolder.Children.IndexOf(cp); 

        (_itemsHolder.Children[index] as ContentPresenter).Tag = 
         (item is TabItem) ? item : (this.ItemContainerGenerator.ContainerFromItem(item)); 
       } 
       _deletedObject = null; 
      } 
     } 
    } 

    if (e.OldItems != null) 
    { 
     foreach (var item in e.OldItems) 
     { 

      _deletedObject = item; 

      // We want to run this at a slightly later priority in case this 
      // is a drag/drop operation so that we can reuse the template 
      // Render is good since a normal Removal of an item will run prior to adding a new one 
      this.Dispatcher.BeginInvoke(DispatcherPriority.Render, 
       new Action(delegate() 
      { 
       if (_deletedObject != null) 
       { 
        ContentPresenter cp = FindChildContentPresenter(_deletedObject); 
        if (cp != null) 
        { 
         this._itemsHolder.Children.Remove(cp); 
        } 
       } 
      } 
      )); 
     } 
    } 
2

您是否試圖將TabControl.ItemsSource綁定到集合視圖,然後根據索引對集合視圖進行排序?然後,您的移動邏輯將簡單地更改索引,並且選項卡項目將相應地排序。

+0

這聽起來像它可能工作的老項目,但我想我可能剛剛發現,沒有按」替代t需要修改我的拖放代碼(該代碼也用於其他地方,所以我希望可以在所有拖放操作中使用這些代碼)。 +1是一個好主意,因爲如果其他人正在尋找類似的東西,這可能會起作用 – Rachel 2010-09-02 13:20:57

相關問題