2013-07-15 75 views
1

我圍繞SortedList做了一個包裝類。我向這個類添加對象,期望它們按字母順序自動排序,但是當我綁定到WPF中的ListBox時,我會以未排序的順序看到它。SortedList似乎沒有排序

public class SortedObservableCollection<T> : ICollection<T>, INotifyPropertyChanged, INotifyCollectionChanged where T : INotifyPropertyChanged//, IComparable<T> 
{ 
    private readonly SortedList<string,T> _innerSortedList; 

    public SortedObservableCollection() 
    { 
     _innerSortedList = new SortedList<string, T>(); 
    } 

    public void Add(T item) 
    { 
     _innerSortedList.Add(item.ToString(), item); 
     this.OnPropertyChanged("Count"); 
     this.OnPropertyChanged("Item[]"); 
     this.OnCollectionChanged(NotifyCollectionChangedAction.Add, item); 
     item.PropertyChanged += ItemPropertyChanged; 
    } 

    void ItemPropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     throw new NotImplementedException(); 
    } 

    public void Clear() 
    { 
     _innerSortedList.Clear(); 
    } 

    public bool Contains(T item) 
    { 
     return _innerSortedList.ContainsKey(item.ToString()); 
    } 

    public void CopyTo(T[] array, int arrayIndex) 
    { 
     throw new NotImplementedException(); 
    } 

    public int Count 
    { 
     get { return _innerSortedList.Count; } 
    } 

    public bool IsReadOnly 
    { 
     get { throw new NotImplementedException(); } 
    } 

    public bool Remove(T item) 
    { 
     bool success = _innerSortedList.Remove(item.ToString()); 
     if (success) 
     { 
      item.PropertyChanged -= ItemPropertyChanged; 
      this.OnPropertyChanged("Count"); 
      this.OnPropertyChanged("Item[]"); 
      this.OnCollectionChanged(NotifyCollectionChangedAction.Remove, item); 
     } 
     return success; 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     throw new NotImplementedException(); 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return _innerSortedList.GetEnumerator(); 
    } 

    protected virtual void OnPropertyChanged([CallerMemberName] String propertyName = "") 
    { 
     if (this.PropertyChanged != null) 
     { 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    protected virtual void OnCollectionChanged(NotifyCollectionChangedAction action, object item) 
    { 
     if (this.CollectionChanged != null) 
     { 
      this.CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, item)); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    public event NotifyCollectionChangedEventHandler CollectionChanged; 
} 

要綁定我簡單地做:

SortedObservableCollection<IRCUser> Users { get; private set; } 
.. fill users... 
lstUsers.ItemsSource = users; 

樣品輸入:

5Muhammad0 
2Muhammad1 
5Muhammad2 

輸出也示出了相似的,只是那些2,4等5的之間非難開始。

注:我IRCUser類沒有實現IComparable,但因爲我只想要一個字母排序,現在我評論了implentation出希望默認的排序中會踢

注2:我已經覆蓋了toString()方法,我忘了提:

public override string ToString() 
{ 
    return (int)Type + Nick; 
} 

UPDATE:

看來國內的sortedList保持正確的順序,但不傳遞到ListBox在正確的順序...

+0

'(int)Type'不是'string',你的覆蓋編譯? – Jodrell

+0

由於您的'SortedList'鍵類型是'string',因此您將獲得按字母順序排列的默認'IComparable '實現。 – Jodrell

+0

試試我的解決方案。 –

回答

1

您無法正確創建事件對象NotifyCollectionChangedEventArgs。該對象根據操作具有不同的構造函數重載。

new NotifyCollectionChangedEventArgs(action, item, index) 

下面是引自MSDN:

初始化NotifyCollectionChangedEventArgs的新實例 類描述了當你創建一個新的項目,則必須使用一個使用新項目的索引超載添加或刪除更改。

NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction, Object, Int32) 

UPDATE 0

而且最好不要使用這種方法ToString的過載比較項目,並利用這個特殊的IComparer<TKey>。 在你的情況下,正確的代碼如下所示:

public void Add(T item) 
{ 
    var key = item.ToString(); 
    _innerSortedList.Add(key, item); 
    this.OnPropertyChanged("Count"); 
    this.OnPropertyChanged("Item[]"); 
    this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, _innerSortedList.IndexOfKey(key))); 
    item.PropertyChanged += ItemPropertyChanged; 
} 

public bool Remove(T item) 
{ 
    var indexOfKey = _innerSortedList.IndexOfKey(item.ToString()); 
    if (indexOfKey == -1) 
     return false; 
    _innerSortedList.RemoveAt(indexOfKey); 
    item.PropertyChanged -= ItemPropertyChanged; 
    this.OnPropertyChanged("Count"); 
    this.OnPropertyChanged("Item[]"); 
    this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, 
     indexOfKey)); 
    return true; 
} 

public IEnumerator<T> GetEnumerator() 
{ 
    return _innerSortedList.Values.GetEnumerator(); 
} 

System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
{ 
    return GetEnumerator(); 
} 

protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs args) 
{ 
    var handler = this.CollectionChanged; 
    if (handler != null) 
    { 
     handler(this, args); 
    } 
} 
+0

好地方!並感謝你。 – sprocket12

0

您正在整理您的數據在item.ToString()這可能不是一個非常有用的價值來排序。

除非被覆蓋,否則它將是類的類型名稱,因此對於添加的所有內容都是相同的。


這顯然會導致一個問題,通用數據應該如何排序。這是IComparable<T>的用途。


你會注意到,有幾個SortedList<T>constructors,讓你傳遞一個IComparable實現定義自己的訂單。

在任何情況下,如果您想使用字符串的默認IComparable實現,您將需要使用根據您的期望順序不同的字符串。不要輸入完全不同的類型名稱。

+0

是的,我已經覆蓋它給字母排序的價值。 – sprocket12

+0

@MuhammadA,我在問題中沒有看到。請顯示'IRCUser'的相關實現,以及'Users'的實例化。 – Jodrell

0

問題是與

_innerSortedList.Add(item.ToString(), item); 

讓我們假設如果產品Project.Test.CustomEntity型,則item.ToString()會給你「Project.Test.CustomEntity」這是越來越排序通過實體的全名而不是價值。

你需要根據你的T的屬性選擇

看一看這個article編寫自定義的分揀機。

0

我不知道,但:

1)如果UI具有數據模板,你顯示樣品輸出沒有IRCUser.ToString()的結果 - 不是,也許,在的ToString( )不會爲排序提供「良好」散列值。

2)通過使用PagedCollectionView來包裝您的收藏,並在那裏設置排序,可能會更好。