2014-12-02 113 views
-1

我有麻烦提出这个问题的逻辑。我有一个窗口中显示的项目列表。如果项目在列表中,则显示该项目。我无法改变这一点。我通过可以编辑的继承类访问列表。我无法以任何方式编辑基类的源代码(包含列表的类)。我正在编辑的类是插入到列表中的类。它也可以访问列表。维护列表顺序删除和添加元素

我需要能够从列表中删除项目并插入它们,同时保持相同的顺序。

例子,如果我的名单是:

1,2,3,4,5 

我删除2,3,4我再有

1,5 

但后来我的顺序添加4,3,2回来。它必须再次不

1,4,3,2,5 

他们必须在原来的顺序,他们在去除显示

1,2,3,4,5 

,这仅仅是一个例子,这些值不能进行排序。他们是在他们被添加的顺序。

所以问题是,我如何删除和添加到列表中的元素,并确保订单保持?

我试过了:

插入空值而不是从列表中删除元素。这不起作用,因为显示空白点。我也尝试记住它们被删除的索引,但是当我将它们插回到列表中时,可能会将多个项目插回到索引0处,并且因为列表缩小而丢失了排序。

我使用的ObservableCollection http://msdn.microsoft.com/en-us/library/ms668604(v=vs.110).aspx

我希望这篇文章是什么,我想实现清晰。

+0

如果您需要保留一个本身并不固有排序的集合的原始顺序(例如排序列表),那么正确的方式来“删除”元素实际上是创建一个已删除不需要的元素的集合的过滤副本。或者,你将不得不保持一个单独的数据结构来跟踪从哪里删除的内容,所以你可以将订单放回原处。 – 2014-12-02 22:59:59

+0

你是否试过使用'SortedList'? – 2014-12-02 23:03:27

+0

指定“它必须显示”的含义。如果仅用于显示目的,则提供返回已排序项目的方法。你可以很容易地做到这一点:'string.Join(“,”,list.OrderBy(x => x))' – 2014-12-02 23:04:31

回答

2

这里有一个想法给你。我实现了我自己的IList<T>类,你想要做什么

首先,我开始这个(我认为):

public class RememberOrderList<T> : IList<T> 
{ 
} 

我再创造了T_inner名单和实施了大部分的通过传递给_inner所需的方法。

public class RememberOrderList<T> : IList<T> 
{ 
    private List<T> _inner = new List<T>(); 
    public int IndexOf(T item) { return _inner.IndexOf(item); } 
    public void RemoveAt(int index) { _inner.RemoveAt(index); } 
    public T this[int index] { get { return _inner[index]; } set { _inner[index] = value; } } 
    public void Clear() { _inner.Clear(); } 
    public bool Contains(T item) { return _inner.Contains(item); } 
    public void CopyTo(T[] array, int arrayIndex) { _inner.CopyTo(array, arrayIndex); } 
    public int Count { get { return _inner.Count; } } 
    public bool IsReadOnly { get { return ((ICollection<T>)_inner).IsReadOnly; } } 
    public bool Remove(T item) { return _inner.Remove(item); } 
    public IEnumerator<T> GetEnumerator() { return _inner.GetEnumerator(); } 
    IEnumerator IEnumerable.GetEnumerator() { return _inner.GetEnumerator(); } 

现在,有两种方法的项目添加到列表 - Insert & Add

Insert是一个问题,因为它指定了索引,我们不希望这样 - 所以会抛出一个NotSupportedException

public void Insert(int index, T item) 
    { 
     throw new NotSupportedException(); 
    } 

Add只需要记住项目的顺序,因为它们被加入和退出之前做了排序。这需要更多的工作。

要跟踪项目的顺序,我正在使用Dictionary<T, int>

private readonly Dictionary<T, int> _order = new Dictionary<T, int>(); 

要对List<T>进行排序,您需要一个IComparer<T>

private class OrderComparer : IComparer<T> 
    { 
     private readonly Dictionary<T, int> _order; 
     public OrderComparer(Dictionary<T, int> order) 
     { 
      _order = order; 
     } 

     public int Compare(T x, T y) 
     { 
      return _order[x].CompareTo(_order[y]); 
     } 
    } 

现在Add很容易。

public void Add(T item) 
    { 
     if (!_order.ContainsKey(item)) 
     { 
      _order[item] = _order.Count; 
     } 
     _inner.Add(item); 
     _inner.Sort(new OrderComparer(_order)); 
    } 

把所有在一起,让我做这件事:

var rol = new RememberOrderList<int>(); 

rol.Add(1); 
rol.Add(2); 
rol.Add(3); 
rol.Add(4); 
rol.Add(5); 

rol.Remove(2); 
rol.Remove(3); 
rol.Remove(4); 

rol.Add(4); 
rol.Add(3); 
rol.Add(2); 

从中我得到这个列表:

Result

现在,只是为了避免混淆,我跑此代码再次使用20代替2,并得到结果{ 1, 20, 3, 4, 5 },因此它按期望的行为排序。

+0

这看起来不错,谢谢。 – marsh 2014-12-16 02:30:20