Laden...

ListView-Spalten (IP-Adressen, Strings) sortieren

Erstellt von spry64 vor 7 Jahren Letzter Beitrag vor 7 Jahren 2.353 Views
S
spry64 Themenstarter:in
52 Beiträge seit 2014
vor 7 Jahren
ListView-Spalten (IP-Adressen, Strings) sortieren

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

771 Beiträge seit 2009
vor 7 Jahren
L
136 Beiträge seit 2015
vor 7 Jahren

Hallo spry64,

Schau mal hier:

IP-Adressen sortieren

Gruss Lhyn

S
spry64 Themenstarter:in
52 Beiträge seit 2014
vor 7 Jahren

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.

S
spry64 Themenstarter:in
52 Beiträge seit 2014
vor 7 Jahren

Hallo spry64,

Schau mal hier:


>

Gruss Lhyn

Ich habe nicht verstanden was seine Klasse ListViewComparer genau macht. Und das soll tatsächlich funktionieren? Wie oben schon erwähnt bietet die Klasse "IPAddress" keine Methode CompareTo an.

S
spry64 Themenstarter:in
52 Beiträge seit 2014
vor 7 Jahren

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?

D
985 Beiträge seit 2014
vor 7 Jahren

Weil die Parse-Methode eine Instanz vom Typ IPAddress zurückliefert? (steht wenigstens so in dem Screenshot)

S
spry64 Themenstarter:in
52 Beiträge seit 2014
vor 7 Jahren

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.

D
985 Beiträge seit 2014
vor 7 Jahren

Ehrlich gesagt würde ich eher eine Implementierung für IComparer<IPAddress> schreiben und den für die Sortierung verwenden.

S
spry64 Themenstarter:in
52 Beiträge seit 2014
vor 7 Jahren

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