简体   繁体   中英

Use a derived ObservableCollection Class

for my Project I Need to have an observableCollection who can sort the Points everytime we add a new Points. After looking through looking for an Idea I felt on a superb Source Code (reference is http://www.dotmaniac.net/simple-sorted-observablecollection/ .)

The Idea is to override the functions from ObservableCollection Class

     public class SortedPoints<T> 
: ObservableCollection<T> where T : IComparable<T> {

protected override void InsertItem(int index, T item)
{
    if (this.Count == 0)
    {
        base.InsertItem(0, item);
        return;
    }

    index = Compare(item, 0, this.Count - 1);

    base.InsertItem(index, item);
}

private int Compare(T item, int lowIndex, int highIndex)
{
    int compareIndex = (lowIndex + highIndex) / 2;

    if (compareIndex == 0)
    {
        return SearchIndexByIteration(lowIndex, highIndex, item);
    }

    int result = item.CompareTo(this[compareIndex]);

    if (result < 0)
    {   //item precedes indexed obj in the sort order

        if ((lowIndex + compareIndex) < 100 || compareIndex == (lowIndex + compareIndex) / 2)
        {
            return SearchIndexByIteration(lowIndex, compareIndex, item);
        }

        return Compare(item, lowIndex, compareIndex);
    }

    if (result > 0)
    {   //item follows indexed obj in the sort order

        if ((compareIndex + highIndex) < 100 || compareIndex == (compareIndex + highIndex) / 2)
        {
            return SearchIndexByIteration(compareIndex, highIndex, item);
        }

        return Compare(item, compareIndex, highIndex);
    }

    return compareIndex;
}

/// <summary>
/// Iterates through sequence of the collection from low to high index
/// and returns the index where to insert the new item
/// </summary>
private int SearchIndexByIteration(int lowIndex, int highIndex, T item)
{
    for (int i = lowIndex; i <= highIndex; i++)
    {
        if (item.CompareTo(this[i]) < 0)
        {
            return i;
        }
    }
    return this.Count;
}

/// <summary>
/// Adds the item to collection by ignoring the index
/// </summary>
protected override void SetItem(int index, T item)
{
    this.InsertItem(index, item);
}

private const string _InsertErrorMessage
   = "Inserting and moving an item using an explicit index are not support by sorted observable collection";

/// <summary>
/// Throws an error because inserting an item using an explicit index
/// is not support by sorted observable collection
/// </summary>
[Obsolete(_InsertErrorMessage)]
public new void Insert(int index, T item)
{
    throw new NotSupportedException(_InsertErrorMessage);
}

/// <summary>
/// Throws an error because moving an item using explicit indexes
/// is not support by sorted observable collection
/// </summary>
[Obsolete(_InsertErrorMessage)]
public new void Move(int oldIndex, int newIndex)
{
    throw new NotSupportedException(_InsertErrorMessage);
}

}

The Problem is I don't have any Idea how to use it with my objects. My objects is a Class RofPoints

public class RofPoints : IComparable
{
    [DisplayName("X")]
    [Description("Punkte der X axis")]
    public int X { get; set; }
    [DisplayName("Y")]
    [Description("Punkte auf der Y Achse")]
    public int Y { get; set; }
    private double dx;
    [DisplayName("dX")]
    [Description("Punkte auf der X Achse mit double values")]
    public double dX
    {
        get
        {
            return dx;
        }

        set
        {
            dx = value;
        }
    }

    private double dy;
    [DisplayName("dY")]
    [Description("Punkte auf der Y Achse mit double values")]
    public double dY
    {
        get
        {
            return dy;
        }
        set
        {
            dy = value;
        }
    }
    public override string ToString()
    {
        return X + " / " + Y;
    }

   public double  CompareTo(double dX)
    {
        return this.dX;  
    }

    public int CompareTo(object obj)
    {
        return dx.CompareTo(obj);
    }
}

}

I would like to use the SortedPoints class to have every new rofpoints added ordered after the dX Attribute.

When I write somewhere in the Code :

 SortedPoints<RofPoints> listofpoints = new SortedPoints<RofPoints>

that doesn't work because the Compiler can't convert implicitly to IComparable. I don't have any Idea how to come further. Could you explain me how to use it or give me an example?

I can't give more code because I am really blocked.

Your RofPoints class must implement the IComparable<RofPoints> interface, and you must implement the method CompareTo(RofPoints other) . So your class should be something like this:

public class RofPoints : IComparable<RofPoints>
{
    [DisplayName("X")]
    [Description("Punkte der X axis")]
    public int X { get; set; }
    [DisplayName("Y")]
    [Description("Punkte auf der Y Achse")]
    public int Y { get; set; }
    private double dx;
    [DisplayName("dX")]
    [Description("Punkte auf der X Achse mit double values")]
    public double dX
    {
        get
        {
            return dx;
        }

        set
        {
            dx = value;
        }
    }

    private double dy;
    [DisplayName("dY")]
    [Description("Punkte auf der Y Achse mit double values")]
    public double dY
    {
        get
        {
            return dy;
        }
        set
        {
            dy = value;
        }
    }

    public int CompareTo(RofPoints other)
    {
        //Here you must compare a RofPoints object to another
    }
}

I have modified my Approach. I wanted to sort automatically the Points when addding new Values. The SortableObservableCollection works when I don't use the MvvM pattern because they are no Events. The SortableObservableCollection is as follow:

public class SortableObservableCollection<T> : ObservableCollection<T>
{
    public void Sort<TKey>(Func<T, TKey> keySelector, System.ComponentModel.ListSortDirection direction)
    {
        switch (direction)
        {
            case System.ComponentModel.ListSortDirection.Ascending:
                {
                    ApplySort(Items.OrderBy(keySelector));
                    break;
                }
            case System.ComponentModel.ListSortDirection.Descending:
                {
                    ApplySort(Items.OrderByDescending(keySelector));
                    break;
                }
        }
    }

    public void Sort<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer)
    {
        ApplySort(Items.OrderBy(keySelector, comparer));
    }

    private void ApplySort(IEnumerable<T> sortedItems)
    {
        var sortedItemsList = sortedItems.ToList();

        foreach (var item in sortedItemsList)
        {
            Move(IndexOf(item), sortedItemsList.IndexOf(item));
        }
    }
}

}

Into the ModelView I try to use it (I can't Show everything because it is a Company Project), it can't work because the sort every time fires Events when the list is beeing modified.

So my question is following How is it possible to stop the Event when sorting the list and when done launching it again?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM