Laden...

GetPropertyInfo eines List Elementes

Erstellt von Dijon vor 10 Jahren Letzter Beitrag vor 10 Jahren 2.200 Views
D
Dijon Themenstarter:in
63 Beiträge seit 2011
vor 10 Jahren
GetPropertyInfo eines List Elementes

Hallo zusammen,

ich hoffe das ich hier richtig bin.

Also erst einmal etwas Vorgeschichte:

Ich brauche ein DataGrid bei dem die letzten beiden Zeilen nicht bei der Sortierung berücksichtigt werden. So ein DataGrid hab ich auch gefunden

C#/WPF Toolkit: DataGrid - Footer Row / summary row

Jetzt hab ich mir das runter geladen und bei mir eingbaut und soweit so gut funktioniert das auch, aber nur unter folgenden bedingungen. Das Element das Sortiert werden soll muss einen publich setter und getter haben, also beim Binding muss TwoWay möglich sein und die Spalte die existiert muss so wie sie gebunden wird auch in dem Objekt das die Zeilen beschreibt vorhanden sein.

Beispiel:


    public class Person
    {
        public string Name { get; set; }
        public string Hobby1 { get; set; }
        public string Hobby2 { get; set; }
        public string Hobby3 { get; set; }
        public string Hobby4 { get; set; }
        public string Hobby5 { get; set; }
    }

Dieser Aufbau funktioniert.

Jetzt möchte ich aber das es eine Variable anzahl an Hobbys möglich ist also habe ich folgendes gebaut.


    public class Person
    {
        public string Name { get; set; }
        public List<string> Hobbies { get; set; }
    }

Jetzt kann ich mir dynamisch DataGridColumns aufbauen die sich dann an die Einzelnen Elemente Binden die in Hobbies stehen und gut ist.

Leider nicht ..... denn der PropertyAccessor der verwendet wird

(Hier zu finden: Fast Dynamic Property Access with C#)

bekommt den PropertyNamen als String übergeben und jetzt wir versucht mit der GetPropertyMethode(string propertyName) zum Beispiel das Property "Hobbies[0]" in der Person zu finden.
Das ist aber so nicht vorhanden und wird natürlich nicht gefunden und es wird eine Exception geworfen und da sind wir auch schon bei meinem Problem.

Ich weiß nicht wie ich das hinbekommen soll das er das Element 0 der liste abfragt und nicht versuch "Hobbies[0]" als eigenes Property zu interpretieren.

Zusätzlich sollte noch zu sagen sein das natürlich Properties die nicht in einer Liste stehen auch noch sortierbar bleiben müssen.

Ich hoffe ihr versteht was ich brauche und wo mein Problem ist und das jemand hilfe für mich hat.

Gruß Dijon

D
615 Beiträge seit 2009
vor 10 Jahren

Hallo Dijon

Deinem gefundenen "Control" konnte ich entnehmen das es sich wohl um WPF handelt.

Ich brauche ein DataGrid bei dem die letzten beiden Zeilen nicht bei der Sortierung berücksichtigt werden. So ein DataGrid hab ich auch gefunden

Du kannst doch einfach das default Grid benutzen und sowas machen :



var sortedData = myData.OrderBy(d=>d.Hallo).ThenBy(d=>d.Welt);
sortedData.Add(myLastItem1);
sotedData.Add(myLastItem2);

myGrid.ItemSource=sortedData;


Beste Grüsse

Diräkt

Edit :

Ich kenne Dein Control nicht, wenn du dieses aber verwenden willst, könntest ja mal folgendes testen:

Hobbies[0] sieht nach einem Array aus, kannst ja versuchen Deine Liste als Array zu deklarieren 😃

Oder du kannst auch sowas versuchen


public string this[this key]
 get { return dictionary[key]; }
    set { dictionary[key] = value; }

D
Dijon Themenstarter:in
63 Beiträge seit 2011
vor 10 Jahren

Hallo Diräkt , danke für deine rasche Meldung.

Dein erste Lösungsvorschlag würde heißen das ich jedesmal wenn ich sortiere müsste ich die letzten beiden Zeilen abschneiden, speichern, dann sortieren und danach die zeilen wieder anfügen. Den Aufwand würde ich mir gerne ersparen deswegen habe ich mir ja dies Lösung die ich gepostet habe gesucht und genutzt ich muss es im endeffekt nur List fähig machen.

Der Zweite ansatz hieße das ich das Personen-Objekt von einer Liste ableiten müsste um dann halt
this[] nutzen zu können aber das ist ja auch nicht mein Ziel.

Mein DataGrid Control ist genau so aufgebaut wie es in dem obrigen Beispiel beschrieben ist , es ist auch das DataGrid aus dem WPFToolkit.

Gruß Dijon

D
615 Beiträge seit 2009
vor 10 Jahren

Hallo Dijon

Den Aufwand würde ich mir gerne ersparen

Ja gerade schön ist es nicht, das stimmt, obwohl Aufwand ist übertrieben, das ist ein 3-4 Zeiler.

Wenn ich mir Deine Struktur anschaue :


public class Person
    {
        public string Name { get; set; }
        public List<string> Hobbies { get; set; }
    }

Ist das für mich :

Main Table:
Name
Detail Table:
Hobbies

Daher würde ich das auch so anzeigen, oder ich versteh wirklich nicht was du meinst. Ist dein Ziel:

Hans   Schwimmen   Super gut
Hans   Rennen      Nicht sehr gut
Reto   Laufen      Perfekt
Reto   Schlafen    Schlecht

Oder was genau willst du erreichen ?

Beste Grüsse

Diräkt

5.658 Beiträge seit 2006
vor 10 Jahren

Oder was genau willst du erreichen ?

So wie ich es verstanden habe, wird nach dem ersten Eintrag vom Hobbies-Property sortiert, die anderen Einträge werden ignoriert:

jetzt wir versucht mit der GetPropertyMethode(string propertyName) zum Beispiel das Property "Hobbies[0]" in der Person zu finden.

Dann wäre evtl. folgende Struktur ganz praktisch:

public class Person
{
     public string Name { get; set; }
     private List<string> Hobbies { get; set; }
     public string Hobby 
     { 
       get { return Hobbies.Count == 0 ? string.Empty : Hobbies[0];
     }
}

Dann kann man nach dem Hobby-Property sortieren lassen.

Christian

Weeks of programming can save you hours of planning

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo Dijon,

die Methode PropertyInfo.GetValue hat einen extra Parameter für den Index-Wert. Du kannst also Hobbies[0] nicht einfach als ersten Parameter übergeben, sondern müsstest es vorher aufteilen und Hobbies als ersten und 0 (verpackt in einem Object-Array) als zweiten Parameter verwenden.

Wenn du die Klasse PropertyAccessor verwendest, müsstest du sie so anpassen, dass sie die Aufteilung vornimmt und dann entsprechenden Code für einen Indexzugriff emittiert.

herbivore

D
Dijon Themenstarter:in
63 Beiträge seit 2011
vor 10 Jahren

Hallo zusammen,

vielen dank für eure vielen Zuschriften und ich merke das ich euch noch ein paar Details schuldig bin.
Das Anzeigen der Daten soll in der View nachher so aussehen.


                       Hobby[0]           Hobby[1]         Hobby[2]
Personname          Fahrradfahren          Laufen          Schwimmen
Hans                  sehr gerne           ungerne          manchmal
Klaus                   ungerne           sehr gerne       sehr gerne

in der letzten Zeile soll dann eine Art auswertung gemacht werden. In etwa so

Auswertung          Es wird gerne       Es wird gerne      Es wird häufig
                  Fahrrad gefahren        gelaufen           geschwommen

Das ist der Plan hinter dem ganzen und es soll natürlich die letzte Zeile nicht verschoben werden
wenn ich nun eine Column Sortiere. Sonst würde die Zeile mit der Auswertung irgendwo stehen
wenn ich nun nach, zum Beispeil, Hobby[1] sortiere.

Ich bekomme an folgenden Stellen probleme:

Im Konstrucktor des PropertyAccessors


public PropertyAccessor(Type targetType, string property)
		{
			this.mTargetType = targetType;
			this.mProperty = property;

            PropertyInfo propertyInfo = targetType.GetProperty(property);
            
			//
			// Make sure the property exists
			//
			if(propertyInfo == null)
			{
				throw new PropertyAccessorException(
					string.Format("Property \"{0}\" does not exist for type "
					+ "{1}.", property, targetType));
			}
			else
			{
				this.mCanRead = propertyInfo.CanRead;
				this.mCanWrite = propertyInfo.CanWrite;
				this.mPropertyType = propertyInfo.PropertyType;
			}
		}

In der Zeile


            PropertyInfo propertyInfo = targetType.GetProperty(property);

hab ich das erste Problem denn dort findet er natürlich nicht "Hobbies[1]" also habe ich versuch das "[0]" abzuschneiden damit der nur nach "Hobbies" schaut und das geht auch.

wenn ich das aber an dieser Stelle mache und in diesem Konstrucktor sage hau mir die "[0]" weg dann kommt es an einer anderen Stelle zum Problem.

Und zwar hier im Konstrucktor vom PropertyComparer


public PropertyComparer(string propertyName, ListSortDirection direction)
        {
            accessor = new PropertyAccessor(typeof(T), propertyName);
            var comparerForPropertyType =
                typeof(Comparer<>).MakeGenericType(typeof(T).GetProperty(propertyName).PropertyType);
            comparer =
                (IComparer)
                comparerForPropertyType.InvokeMember("Default",
                                                     BindingFlags.Static | BindingFlags.GetProperty |
                                                     BindingFlags.Public, null, null, null);
            SetListSortDirection(direction);
        }

In dieser Zeile wird dann eine NullReferenceException geworfen wenn propertyName "Hobbies[0]" ist.


            var comparerForPropertyType =
                typeof(Comparer<>).MakeGenericType(typeof(T).GetProperty(propertyName).PropertyType);

Wenn ich also hingehe und noch vor dem PropertyComparer die "[0]" müsstes es gehen aber dann bekomme ich hier eine Ausnahme.


        public int Compare(T x, T y)
        {
            return reverse * comparer.Compare(accessor.Get(x), accessor.Get(y));
        }

Das ist dann eine ArgumentException mit dem Hinweis: > Fehlermeldung:

Mindestens ein Objekt muss IComparable implementieren.

(Was die Nachricht bedeutet weiß ich, ich weiß nur noch wo ich den IComparable einbinden soll)

Wenn ich jetzt im Debugger weiter gehe dann komme ich zu folgendem Punkt.


Sort(0, countToSort, comparerLast); 

Das ist in der Footlist die von List erbt und dort wird eine:

InvalidOperationException geworfen mit der Aussage

Fehler beim Vergleichen von zwei Elementen im Array

So das ist alles was ich dazu sagen kann weil mehr bekomme ich vom Debugger nicht.

Gruß Dijon

M
334 Beiträge seit 2007
vor 10 Jahren

Naja das ist doch schon recht eindeutig. 🙂

Mach deine Hobby-Objekt vergleichbar (IComparable implementieren) und bau eine Eigenschaft ein, welches die Zusammenfassungszeile kennzeichnet (sofern ich das richtig interpretiert habe, dass die Zusammenfassung auch ein Hobby-Objekt ist)

Wenn Hobby.IsSummary -> beim vergleichen immer nach ganz unten sortieren.

D
Dijon Themenstarter:in
63 Beiträge seit 2011
vor 10 Jahren

Hobby ist einfach nur ein string und da steht nicht direkt das Hobby drin sonder nur wie gerne das hobby gemacht wir

wie gesagt im Person Objekt existert nur

List<string> Hobbies;

Für mich ist halt die Frage wie das DataGrid das grundsätlich löst mit dem Sortieren denn
ihm ist es ja völlig wumpe ob da jetzt ein Element eines Arrays drin steht oder ob es
ein Attribut ist.

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo Dijon,

Für mich ist halt die Frage wie das DataGrid das grundsätlich löst mit dem Sortieren

eben über den IComparer. Lies mal alles gesagte noch mal durch. Du solltest jetzt alle Informationen haben, die du brauchst ...

... vorausgesetzt du beherrschst die Grundlagen, die wir voraussetzen, siehe [Hinweis] Wie poste ich richtig? Punkt 1.1.1 und nutzt die Dokumentation, siehe Punkt 1.1.

herbivore