Hallo,
ich habe in meinem ListView folgende Daten:
public class Teilnehmer
{
public string Zugriffszeit { get; set; }
public string Name { get; set; }
public IPAddress IP { get; set; }
}
public MainWindow()
{
InitializeComponent();
List<Teilnehmer> listenElement = new List<Teilnehmer>();
listenElement.Add(new Teilnehmer() { Name = "Objekt1", Zugriffszeit = "30ms", IP = IPAddress.Parse("10.1.1.90") });
listenElement.Add(new Teilnehmer() { Name = "Objekt2", Zugriffszeit = "31ms", IP = IPAddress.Parse("10.1.1.8") });
listenElement.Add(new Teilnehmer() { Name = "Objekt3", Zugriffszeit = "32ms", IP = IPAddress.Parse("10.1.1.10") });
listenElement.Add(new Teilnehmer() { Name = "Objekt4", Zugriffszeit = "33ms", IP = IPAddress.Parse("10.1.1.9") });
listenElement.Add(new Teilnehmer() { Name = "Objekt5", Zugriffszeit = "34ms", IP = IPAddress.Parse("10.1.1.100") });
listenElement.Add(new Teilnehmer() { Name = "Objekt5", Zugriffszeit = "35ms", IP = IPAddress.Parse("10.1.2.10") });
listenElement.Add(new Teilnehmer() { Name = "Objekt5", Zugriffszeit = "36ms", IP = IPAddress.Parse("10.1.2.2") });
ListViewListe.ItemsSource = listenElement;
}
und mit folgendem Code kann ich nur die Spalten "Zugriffszeit" und "Name" sortieren.
private ListSortDirection _sortDirection;
private GridViewColumnHeader _sortColumn;
//Dieser Ereignishandler sortiert die Spalten des ListView absteigend oder ansteigend
private void GridViewColumnHeaderClickHandler(object sender, RoutedEventArgs e)
{
GridViewColumnHeader column = e.OriginalSource as GridViewColumnHeader;
if (column == null)
{
return;
}
if (_sortColumn == column)//Falls die gleiche Spalte nochmals angeklickt wurde
{//Sortierreihenfolge toggeln
_sortDirection = _sortDirection == ListSortDirection.Ascending ?//aufsteigend
ListSortDirection.Descending ://absteigend
ListSortDirection.Ascending;
}
else
{
// Entferne die Pfeile vom vorigen Header
if (_sortColumn != null)
{
_sortColumn.Column.HeaderTemplate = null;
}
_sortColumn = column;
_sortDirection = ListSortDirection.Ascending;
}
//Füge Pfeile für die Sortierfolge dem ListView-Header hinzu
if (_sortDirection == ListSortDirection.Ascending)
{
column.Column.HeaderTemplate = Resources["HeaderTemplateArrowUp"] as DataTemplate;
}
else
{
column.Column.HeaderTemplate = Resources["HeaderTemplateArrowDown"] as DataTemplate;
}
ICollectionView resultDataView = CollectionViewSource.GetDefaultView(ListViewListe.ItemsSource);
resultDataView.SortDescriptions.Clear();
resultDataView.SortDescriptions.Add(new SortDescription(column.Tag.ToString(), _sortDirection));
}
Mit IP-Adressen klappt es leider nicht. Wie könnte ich das machen? Die IP-Adressen sollten dann so sortiert sein:
10.1.1.8
10.1.1.9
10.1.1.10
10.1.1.90
10.1.1.100
10.1.2.2
10.1.2.10
Schau mal in
>
Also den Teil wo er eine PersonComparer-Klasse verwendet habe ich in "TeilnehmerComparer" umgeändert und das sieht wie folgt aus:
public class TeilnehmerComparer : ListViewCustomComparer<Teilnehmer>
{
/// <summary>
/// Compares the specified x to y.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns></returns>
public override int Compare(Teilnehmer x, Teilnehmer y)
{
try
{
String valueX = String.Empty, valueY = String.Empty;
switch (SortBy)
{
default:
case "Zugriffszeit":
valueX = x.Zugriffszeit;
valueY = y.Zugriffszeit;
break;
case "Name":
valueX = x.Name;
valueY = y.Name;
break;
case "IP":
if (SortDirection.Equals(ListSortDirection.Ascending)) return x.IP.Address.CompareTo(y.IP.Address);
else return (-1) * x.IP.Address.CompareTo(y.IP.Address);
}
if (SortDirection.Equals(ListSortDirection.Ascending)) return String.Compare(valueX, valueY);
else return (-1) * String.Compare(valueX, valueY);
}
catch (Exception)
{
return 0;
}
}
}
Die Klasse Teilnehmer so ähnlich wie "Person" aber mit meinen Daten
und das Füllen der Liste sieht so aus:
itemSource = new ObservableCollection<Teilnehmer>();
itemSource.Add(new Teilnehmer("Objekt1", "30ms",IPAddress.Parse("10.1.1.90")));
itemSource.Add(new Teilnehmer("Objekt2", "31ms",IPAddress.Parse("10.1.1.8") ));
itemSource.Add(new Teilnehmer("Objekt3", "32ms", IPAddress.Parse("10.1.1.10") ));
itemSource.Add(new Teilnehmer("Objekt4", "33ms",IPAddress.Parse("10.1.1.9") ));
itemSource.Add(new Teilnehmer("Objekt5", "34ms",IPAddress.Parse("10.1.1.100") ));
itemSource.Add(new Teilnehmer("Objekt5", "35ms", IPAddress.Parse("10.1.2.10") ));
itemSource.Add(new Teilnehmer("Objekt5", "36ms", IPAddress.Parse("10.1.2.2") ));
lstView.ItemsSource = itemSource;
Hier werden wieder "Name" und "Zugriffszeit" richtig sortiert, aber nicht die IP-Adressen
PS: Die Klasse IPAddress bietet keine CompareTo-Methode, daher habe ich "IP.Address.CompareTo" verwendet. Vielleicht liegt es ja daran.
Probiere mal diese CompareTo-Methode: Extending the IPAddress object to allow relative comparisons of two IP addresses
Probiere mal diese CompareTo-Methode:
>
Hallo Danke erstmal für den Link!
So sieht jetzt meine Klasse "Teilnehmer" aus
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Net;
namespace WpfListViewSorting
{
public class Teilnehmer : INotifyPropertyChanged
{
#region [ Constructor ]
/// <summary>
/// Initializes a new instance of the <see cref="Teilnehmer"/> class.
/// </summary>
/// <param name="Name">Okject-Name.</param>
/// <param name="Zugriffszeit">Time.</param>
/// <param name="IP">IP-Address.</param>
public Teilnehmer(String Name, String Zugriffszeit, ComparibleIPAddress IP)
{
_name = Name;
_zugriffszeit = Zugriffszeit;
_ip = IP;
}
#endregion
#region [ Fields ]
private String _zugriffszeit;
private String _name;
private ComparibleIPAddress _ip;
#endregion
#region [ Properties ]
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>Object-Name.</value>
public String Name
{
get { return _name; }
set
{
if (_name == value) return;
_name = value;
OnPropertyChanged("Name");
}
}
/// <summary>
/// Gets or sets the time.
/// </summary>
/// <value>Zugriffszeit.</value>
public String Zugriffszeit
{
get { return _zugriffszeit; }
set
{
if (_zugriffszeit == value) return;
_zugriffszeit = value;
OnPropertyChanged("Zugriffszeit");
}
}
/// <summary>
/// Gets or sets the IP.
/// </summary>
/// <value>IP-Adress.</value>
public ComparibleIPAddress IP
{
get { return _ip; }
set
{
if (_ip == value) return;
_ip = value;
OnPropertyChanged("IP");
}
}
#endregion
#region [ Events ]
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region [ Methods ]
/// <summary>
/// Called when [property changed].
/// </summary>
/// <param name="propertyName">Name of the property.</param>
protected void OnPropertyChanged(String propertyName)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}
Nun kriege ich aber folgende Fehlermeldung beim Hinzufügen eines Objekts in die Liste:
Siehe Anhäng
Da scheint doch alles richt zu sein. Wieso die Fehlermeldung?
Weil die Parse-Methode eine Instanz vom Typ IPAddress
zurückliefert? (steht wenigstens so in dem Screenshot)
Weil die Parse-Methode eine Instanz vom Typ
IPAddress
zurückliefert? (steht wenigstens so in dem Screenshot)
Ja und wenn ich folgendes mache
itemSource.Add(new Teilnehmer("Objekt1", "30ms", (ComparibleIPAddress)IPAddress.Parse("10.1.1.90")));
Kommt eine Exception während der Laufzeit, dass System.Net.IPAddress nicht in ComparableIPAddress umgewandelt werden kann. Was ist jetzt zu machen um die Methode CompareTo auf IP-Adressen anwenden zu können. Bin etwas verwirrt gerade.
Ehrlich gesagt würde ich eher eine Implementierung für IComparer<IPAddress>
schreiben und den für die Sortierung verwenden.
Ehrlich gesagt würde ich eher eine Implementierung für
IComparer<IPAddress>
schreiben und den für die Sortierung verwenden.
Danke für den Tipp. Ich habe die Compare-Methode aus diesem Algorithmus genommen. Damit klappt es.
https://www.dotnetperls.com/alphanumeric-sorting