2010-09-02 140 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

相关问题