Ordine ObservableCollection con Linq e IComparer
-
11-12-2019 - |
Domanda
Voglio ordinare in ordine alfabetico ObservableCollection perché non voglio creare un'altra associazione.Ho visto che abbiamo potuto utilizzare Linq e il metodo OrderBy.Vorrei anche usare un IComparer perché dovrò organizzare complesso di dati (liste nelle altre liste), ma VS mi dice che non posso usare la mia operatore di confronto :
(dare il link dell'errore, perché il mio VS è in francese)
http://msdn.microsoft.com/en-gb/library/hxfhx4sy%28v=vs.90%29.aspx
Tutte le idee ?
private void SortGraphicObjectsAscending(object sender, RoutedEventArgs e)
{
GraphicObjects.OrderBy(graphicObject => graphicObject.Nom, new GraphicObjectComparer(true));
}
E il mio operatore di confronto (che è già testato)
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;
}
}
Grazie per le vostre risposte.Comunque ho un altro problema.Come Michael ha detto, io uso un più complesso il confronto, ma per un'altra entità.Questa entità viene visualizzato con una struttura gerarchica, ed un oggetto che può contenere un elenco di altri oggetti dello stesso tipo.
Ho potuto testare il mio GraphicObject becuse non ho accesso al DB (che non c'era oggetto al momento).Con il test sulla mia VideoEntity sembra che il mio ObservableCollection non è ordinato come voglio io (ho creato un altro).Voglio invertire, in ordine alfabetico, ma non funziona.
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;
}
PS :a proposito, sto agendo su un DependancyProperty.È il modo corretto per farlo ?(Io sono nuovo su WPF)
Soluzione
Il problema è la definizione di OrderBy
che si sta tentando di utilizzare:
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
IComparer<TKey> comparer
)
Ci sono due diversi parametri generici per questo metodo: TSource
e TKey
. TSource
è ovvio, è lo stesso come il TSource
per l'origine IEnumerable
.Il TKey
parametro è quello che il compilatore cerca, e in mancanza, di dedurre perché si sta tentando di utilizzare due tipi diversi.La chiamata:
GraphicObjects.OrderBy(graphicObject => graphicObject.Nom, new GraphicObjectComparer(true));
Il primo parametro è un Func<GraphicObject, string>
ma il secondo parametro è un IComparer<GraphicObject>
;questo significa che si sta utilizzando TKey = string
in un luogo e TKey = GraphicObject
negli altri.
Il primo parametro, il Func<>
delegato, è il "tasto di selezione";è come dire OrderBy
i valori da ordinare.Dal momento che il IComparer<>
è l'ordinamento in base al tutto GraphicObject
istanza, che cosa si dovrebbe essere selezionando la chiave:
GraphicObjects.OrderBy(go => go, new GraphicObjectComparer(true));
Sto supponendo che il vostro uso di questo oggetto è in realtà più complesso di quello che hai mostrato, perché il campione del confronto è piuttosto ridondante:
var asc = GraphicObjects.OrderBy(go => go.Nom);
var desc = GraphicObjects.OrderByDescending(go => go.Nom);
Inoltre, si noti che il codice di esempio, in realtà non fare nulla con il neo-elenco ordinato, in modo che solo ottenere buttato fuori.LINQ operazioni mai cambiare la sorgente di enumerabile, restituiscono sempre una nuova, trasformata copia di esso, invece.
Altri suggerimenti
il comparer
confronta GraphicObject
.così il vostro OrderBy
dovrebbe essere
GraphicObjects.OrderBy(graphicObject => graphicObject,
new GraphicObjectComparer(true));
o semplicemente utilizzare
GraphicObjects.OrderBy(graphicObject => graphicObject.Nom);
BTW, OrderBy
non ordina posto, si deve assegnare il restituiti IEnumerable<GraphicsObject>
per una variabile
Il problema è che il Programma utilizza GraphicObject, ma è possibile confrontare le stringhe.
Se si ha realmente bisogno di un tuo ordine, è possibile utilizzare questo operatore di Confronto:
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 si fornisce un GraphicObject al tuo operatore di confronto, non una stringa.
Per ordinato ObservableCollection riflette tutte le modifiche nella raccolta di origine, è possibile utilizzare il mio ObservableComputations biblioteca.Utilizzando questa libreria è possibile un codice come questo:
var sortedGraphicObjects = GraphicObjects.Ordering(
graphicObject => graphicObject.Nom, new GraphicObjectComparer(true));
sortedGraphicObjects è ObservableCollection e riflette tutte le modifiche in GraphicObjects raccolta e Nom proprietà.Assicurarsi che Nom proprietà notifica di modifiche INotifyPropertyChanged l'interfaccia.