Pregunta

Quiero ordenar alfabéticamente una ObservableCollection porque no quiero tener que crear otro enlace.He visto que podríamos usar Linq y el método OrderBy.También me gustaría usar un IComparer personal porque tendré que organizar datos complejos (listas en otras listas), pero VS me dice que no puedo usar mi propio comparador:

(te doy el enlace del error porque mi VS está en francés)

http://msdn.microsoft.com/en-gb/library/hxfhx4sy%28v=vs.90%29.aspx

Algunas ideas ?

private void SortGraphicObjectsAscending(object sender, RoutedEventArgs e)
    {
        GraphicObjects.OrderBy(graphicObject => graphicObject.Nom, new GraphicObjectComparer(true));

    }

Y mi propio comparador (que ya está probado)

public class GraphicObjectComparer : IComparer<GraphicObject>
{
    int order = 1;

    public GraphicObjectComparer(Boolean ascending)
    {
        if (!ascending)
        {
            order = -1;
        }
    }

    public GraphicObjectComparer()
    {

    }

    public int Compare(GraphicObject x, GraphicObject y)
    {
        return String.Compare(x.Nom, y.Nom, false) * order;
    }

}

Gracias por tus respuestas.De todos modos tengo otro problema.Como dijo Michael, uso un comparador más complejo pero para otra entidad.Esta entidad se muestra con un árbol jerárquico y un objeto puede contener una lista de otros objetos del mismo tipo.

No pude probar mi GraphicObject porque no tengo acceso a la base de datos (no había ningún objeto en este momento).Con las pruebas en mi VideoEntity parece que mi ObservableCollection no está ordenada como quiero (creo otra).Quiero invertirlo alfabéticamente pero no funciona.

public class VideoEntityComparer : IComparer<VideoEntity>
{

    int order = 1;

    public VideoEntityComparer(Boolean ascending)
    {
        if (!ascending)
        {
            this.order = -1; // so descending
        }
    }

    public VideoEntityComparer()
    {

    }

    public int Compare(VideoEntity x, VideoEntity y)
    {
        if ((x is BaseDirectory && y is BaseDirectory) || (x is BaseSite && y is BaseSite) || (x is VideoEncoder && y is VideoEncoder))
        {
            return string.Compare(x.Nom, y.Nom, false) * order; // only objects of the same type are sorted alphabetically
        }
        else if ((x is BaseDirectory && y is BaseSite) || (x is BaseSite && y is VideoEncoder))
        {
            return -1;
        }else
        {
            return 1;
        }
    }
}

private void SortDirectoriesDescending(object sender, RoutedEventArgs e)
    {
        ObservableCollection<BaseDirectory> tempDir  = new ObservableCollection<BaseDirectory>(
            Directories.OrderBy(directory => directory, new VideoEntityComparer(false)));
        Directories = tempDir;
    }

PD:por cierto, estoy actuando en una DependancyProperty.¿Es la forma correcta de hacerlo?(Soy nuevo en WPF)

¿Fue útil?

Solución

El problema con esa línea está en la definición de OrderBy que estás intentando usar:

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector,
    IComparer<TKey> comparer
)

Hay dos parámetros genéricos diferentes para este método: TSource y TKey. TSource es obvio, es lo mismo que el TSource para la fuente IEnumerable.El TKey El parámetro es el que el compilador intenta inferir, y no logra, porque está intentando utilizar dos tipos diferentes.Tu llamada:

GraphicObjects.OrderBy(graphicObject => graphicObject.Nom, new GraphicObjectComparer(true));

Su primer parámetro es un Func<GraphicObject, string> pero su segundo parámetro es un IComparer<GraphicObject>;esto significa que estás usando TKey = string en un solo lugar y TKey = GraphicObject en el otro.

El primer parámetro, el Func<> delegado, es el "selector de claves";así es como lo dices OrderBy por qué valores ordenar.desde tu IComparer<> está clasificando según el completo GraphicObject instancia, eso es lo que deberías seleccionar como clave:

GraphicObjects.OrderBy(go => go, new GraphicObjectComparer(true));

Supongo que su objeto comparador personalizado es en realidad más complejo de lo que ha mostrado, porque su comparador de muestra es bastante redundante:

var asc = GraphicObjects.OrderBy(go => go.Nom);
var desc = GraphicObjects.OrderByDescending(go => go.Nom);

Además, tenga en cuenta que su código de muestra en realidad no hace nada con la lista recién ordenada, por lo que simplemente se descarta.operaciones LINQ nunca cambian la fuente enumerable, siempre devuelven una copia nueva transformada del mismo.

Otros consejos

su comparer compara GraphicObject.entonces tus OrderBy debiera ser

 GraphicObjects.OrderBy(graphicObject => graphicObject,
                                                 new GraphicObjectComparer(true));

o simplemente usar

GraphicObjects.OrderBy(graphicObject => graphicObject.Nom);

POR CIERTO, OrderBy no se ordena en el lugar, debe asignar el resultado devuelto IEnumerable<GraphicsObject> a una variable

El problema es que su comparación usa graphicObject, pero comparas cadenas.

Si realmente necesita su propio pedido, puede usar este comparación:

public class GraphicObjectComparer : IComparer<string>
{
    int order = 1;

    public GraphicObjectComparer(Boolean ascending)
    {
        if (!ascending)
        {
            order = -1;
        }
    }

    public GraphicObjectComparer()
    {

    }

    public int Compare(string x, string y)
    {
        return String.Compare(x, y, false) * order;
    }
}

O usted proporciona un GraphicObject a su comparación, no una cadena.

Para ordenar la selección de observabilidad refleja todos los cambios en la recopilación de origen, puede usar mi Biblioteca observableComputaciones Biblioteca.Usando esta biblioteca puedes codificar así:

var sortedGraphicObjects = GraphicObjects.Ordering(
    graphicObject => graphicObject.Nom, new GraphicObjectComparer(true));

SortedGraphicObjects es observableCollection y refleja todos los cambios en la recopilación de graphicObjects y la propiedad de NOM.Asegúrese de que la propiedad de NOM no notifique los cambios a través de Interfaz de inotifypropertyChanged .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top