myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Grundlagen von C# » An abgeleitete Collection gebundene ListBox bleibt leer
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

An abgeleitete Collection gebundene ListBox bleibt leer

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
pisacou
myCSharp.de-Mitglied

Dabei seit: 23.09.2015
Beiträge: 9
Entwicklungsumgebung: ShaaprDevelop


pisacou ist offline

An abgeleitete Collection gebundene ListBox bleibt leer

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,
wie unten gezeigt, versuche ich, an eine eigene Collection (abgeleitet von System.Collections.ObjectModel.Collection) eine ListBox zu binden. ANhand der Ausgaben in den MessageBopxen ist zu erkenne, dass die Collection funktioniert. Sowohl die Count Eigenschaft als auch der Zugriff auf die Elemente der COllection funktionieren.
Leider bleibt die an die Collection gebundene ListBox leer. Das binden an eine List<string> funktioniert aber.
An den MessageBoxen erkennt man ausserdem, dass die Collection-Methoden nach dem BInding nicht aufgerufen werden.
Das Ändern des Basistyps meiner COllection von System.Collections.ObjectModel.Collection auf System.Collections.Generic.List ändert auch nichts-
Warum bleibt die ListBox leer?
Der Code stammt übrigens aus einem normalen VS2017 WinForms Projekt. Die restlichen Projektdateien dürften irrelevant sein.
LG, Pisacou

C#-Code:
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Windows.Forms;

namespace ListBoxBindingTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            ListBox teamBox = new ListBox();
            List<string> members = new List<string>{ "Member 0", "Member 1","Member 2","Member 3", "Member 4"};
            TeamList tl = new TeamList(new Team(5));
            //MessageBox.Show(tl.Count + " members in team, member 2: '" + tl[2]+"'");//bringt das erwartete Ergebnis
            teamBox.DataSource = tl;
            //teamBox.DataSource = members;//bringt das erwartete Ergebnis
            Controls.Add(teamBox);
        }
    }

    class Team
    {
        public Team(int count)
        {
            MemberCount = count;
        }

        public int MemberCount { get; }

        public string GetMember(int index)
        {
            return "Member " + Convert.ToString(index);
        }
    }
    class TeamList: List<string>
    {
        private Team team;

        public TeamList(Team team)
        {
            this.team = team;
        }

        public new int Count{
            get {
                MessageBox.Show("In TeamList.Count, members in team " + team.MemberCount);
                return team.MemberCount;
            }
        }

        public new string this[int index]
        {
            get {
                MessageBox.Show("Returning member " + index);
                return team.GetMember(index);
            }
        }
    }
}
09.08.2019 21:17 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
MrSparkle MrSparkle ist männlich
myCSharp.de-Team

avatar-2159.gif


Dabei seit: 16.05.2006
Beiträge: 5.176
Herkunft: Leipzig


MrSparkle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Du fügst nirgendwo einen Eintrag zur Liste hinzu. Dazu müßtest du die Add-Methode der List-Klasse aufrufen.
09.08.2019 21:48 Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.311
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist online

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Oder die Members auch noch an den TeamList-Konstruktor übergeben und den base-Konstruktor damit aufrufen:

C#-Code:
public TeamList(Team team, IEnumerable<string> members)
  : base(members)
{
    this.team = team;
}

PS: Wenn die Team-Klasse einzig für die Anzahl der Member zuständig sein soll, dann ist diese aber überflüssig, da die Anzahl ja durch die Anzahl der Elemente in TeamList (bzw. List<string>) gegeben ist (ebenso dann die Überladungen von Count und this[int]).

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Th69 am 10.08.2019 09:17.

10.08.2019 09:06 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
T-Virus T-Virus ist männlich
myCSharp.de-Mitglied

Dabei seit: 17.04.2008
Beiträge: 1.269
Entwicklungsumgebung: Visual Studio, Codeblocks, Edi
Herkunft: Nordhausen, Nörten-Hardenberg


T-Virus ist offline Füge T-Virus Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich würde sogar noch einen Schritt weiter gehen.
Erst einmal würde ich eine TeamMember Klasse anlegen, die ein Mitglied des Teams darstellt.
Die Team Klasse würde ich neu implementieren, diese würde dann die Property Members vom Typen List<TeamMember> anbieten.
Damit wäre dann eine sinnvollere Umsetzung als die Ableitung von List<string> umgesetzt.

Die TeamMember Klasse kann dann in Ruhe ausgebaut werden und enthält alle nötigen Informationen über ein Mitglied des Teams während die Team Klasse als Container für die Mitglieder eines Teams dient sowie auch Informationen über das Team selbst enthalten kann.

Somit sind die Daten alle sauber gekapselt und die unnötige Ableitung von List<string> durch saubere Kapselung ebenfalls erledigt.
Die Informationen über die Anzahl der Mitglieder kann man dann einfach über Members.Count abrufen.

T-Virus
10.08.2019 11:27 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
pisacou
myCSharp.de-Mitglied

Dabei seit: 23.09.2015
Beiträge: 9
Entwicklungsumgebung: ShaaprDevelop

Themenstarter Thema begonnen von pisacou

pisacou ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,
danke für die Antworten.
MrSparkle/Th69: Meine TeamList war eigentlich als wrapper um ein Team gedacht, um die Team-Klasse auch als List verwenden zu können, wenn erforderlich. Sprich: die members existieren nur im Team, und die TeamList-Klasse sorgt nur dafür, dass auf die member über das List-interface zugegriffen werden kann. Es war nicht geplant, die Members zusätzlich zum Team auch in der TeamList-Klasse zu erstellen.

T_Virus: Der gepostete Code ist stark vereinfacht. Im realen Projekt geht es nicht um strings, sondern um kompliziertere Objekte, und die "echte" Team-Klasse ist auch komplexer als die gepostete. Die echte Team-Klasse nutzt aber Collections zur internen Speicherung von Objekten gleichen Typs. Ich hatte auch schon darüber nachgedacht, diese internen Collections einfach als ReadOnlyCollections zugänglich zu machen, aber das schien mir eher eine quick & diurty Lösung zu sein. Im normalen Gebrauch ist es nämlich unnötig, auf die interne Collection zugreifen zu können. Ich brauche diese Option nur zum Anzeigen der Objekte in einer ListBox, und da schien mir ein wrapper die sauberere Lösung zu sein, anstatt die Team-Klasse nochmal anzufassen. Ich werde den Weg mit der Property trotzdem mal testen, und die interne Collection als ReadOnly-Variante so zugänglich machen.
Mir ist aber immer noch nicht klar, warum die ListBox den Inhalt der TeamList nicht anzeigt. Offenbar nutzt die ListBox andere Methoden als Count und den Indexer, um auf den Inhalt ihrer DataSource zuzugreifen. Da werde ich wohl noch etwas rumprobieren müssen, bis ich das Verhalten verstanden habe.
11.08.2019 18:26 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 12.901
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Wenn Du Code nur "stark vereinfachst" zeigst, dann sinkt natürlich auch die potentielle Qualität von Beiträgen.

Dir bringts nichts, wenn man am Thema vorbei redet und Helfer haben i.d.R. auch keine Lust auf wissentliches Rumstochern. Daumen hoch

Zitat:
Mir ist aber immer noch nicht klar, warum die ListBox den Inhalt der TeamList nicht anzeigt.

Zeig den echten Code, dann sieht man evtl. auch das Problem.
11.08.2019 18:29 Beiträge des Benutzers | zu Buddylist hinzufügen
pisacou
myCSharp.de-Mitglied

Dabei seit: 23.09.2015
Beiträge: 9
Entwicklungsumgebung: ShaaprDevelop

Themenstarter Thema begonnen von pisacou

pisacou ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Abt,
die starke Vereinfachung habe ich aufgrund von Abschnitt 4.1 aus dem "Wie poste ich richtig?" Thread erstellt. In dem Abschnitt geht es zwar um das Anhängen von Projekten an Beiträge, für mich war es aber naheliegend, das ganze auch auf Beispielcodes zu übertragen: keinen unnötigen Code, der mit dem eigentlichen Problem nichts zu tun hat, sondern nur davon ablenkt, und es Helfern erschwert, das eigentliche Problem nachzuvollziehen. Stattdessen habe ich einen möglichst einfachen Code gepostet, der das in der Frage beschriebene Problem zeigt. Ich bitte dafür um Entschuldigung, dass ich nicht klar gemacht habe, dass der gepostete Code nur ein vereinfachtes Beispiel ist.
Der echte Code verhält sich aber genauso wie der vereinfachte Code: mein List-Wrapper um ein Objekt wird beim Binden an eine ListBox anders behandelt als eine "richtige" List. Deshalb ich fest überzeugt, dass das Posten des echten Codes nichts zur Klärung beitragen wird.
Nach T-Virus' Post ist der Ansatz mit dem Wrapper ohnehin kein guter Weg.
Falls du dennoch die Antwort auf die einizge Frage in meinem Eingangspost ("Warum bleibt die ListBox leer?") für hilfreich hältst, kann ich gerne die Antwort posten, sobald ich sie gefunden habe.
LG, Pisacou
11.08.2019 20:57 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.311
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist online

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Die Antwort haben wir dir doch schon in den ersten beiden Beiträgen gegeben. Eine leere List<> kann nun mal nicht in einer ListBox angezeigt werden (für das DataBinding ist nur die IEnumerable-Schnittstelle relevant, nicht die Count-Eigenschaft - auch wenn diese konsistent sein sollten, was sie eben in deiner gezeigten Implementierung nicht ist)...
11.08.2019 21:26 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
pisacou
myCSharp.de-Mitglied

Dabei seit: 23.09.2015
Beiträge: 9
Entwicklungsumgebung: ShaaprDevelop

Themenstarter Thema begonnen von pisacou

pisacou ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo TH69,
danke für den (erneuten) Hinweis.
Um das Thema abzuschliessen, hier die um eine konsistente IEnumerable-Implementierung ergänzte TeamList-Klasse, mit der die Teammitglieder tatsächlich in der ListBox angezeigt werden.

C#-Code:
    class TeamList: List<string>, IEnumerable
    {
        private Team team;

        public TeamList(Team team)
        {
            this.team = team;
        }

        public new IEnumerator GetEnumerator()
        {
            for (int i = 0; i < team.MemberCount; i++)
            {
                yield return team.GetMember(i);
            }
        }

        public new int Count{
            get {
                return team.MemberCount;
            }
        }

        public new string this[int index]
        {
            get {
                return team.GetMember(index);
            }
        }
    }
13.08.2019 21:06 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 12.901
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Du verfälscht damit das komplette Verhalten von List<T> und ignorierst auch das OOP Konzept.
Das ist alles andere als gut; ich kann von der Implementierung nur abraten.
Der Grundfehler ist hier, dass Du die Klasse Team schon falsch im Sinne der Architektur implementierst hast.

Der Rest ist einfach nur ein Folgefehler.

C#-Code:
public class Team
{
    public IList<string> Members { get; set; }
}

Nun kannst Du Members einfach binden.
13.08.2019 21:58 Beiträge des Benutzers | zu Buddylist hinzufügen
Palladin007 Palladin007 ist männlich
myCSharp.de-Mitglied

Dabei seit: 03.02.2012
Beiträge: 1.174
Entwicklungsumgebung: Visual Studio 2017
Herkunft: NRW


Palladin007 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Oder:

C#-Code:
public class TeamMemberList : IList<string>
{
    private readonly IList<string> _inner;

    // Implementierung über "_inner" plus die eigenen Anpassungen.
}

Die  Collection<T>-Klasse (oder die Ableitung  ObservableCollection<T>) bietet neben den üblichen IList<T>-Funktionen auch noch Möglichkeiten, sie zu manipulieren, indem man ein paar der Methoden überschreibt. Das kann Arbeit ersparen, es kann's aber auch komplizierter machen.
13.08.2019 22:05 Beiträge des Benutzers | zu Buddylist hinzufügen
T-Virus T-Virus ist männlich
myCSharp.de-Mitglied

Dabei seit: 17.04.2008
Beiträge: 1.269
Entwicklungsumgebung: Visual Studio, Codeblocks, Edi
Herkunft: Nordhausen, Nörten-Hardenberg


T-Virus ist offline Füge T-Virus Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Was Abt hier vorschlägt, entspricht auch meinem Ansatz oben bei dem ich dir sogar eine Anleitung zur sauberen Kapselung sowie passenden Klassen Vorgaben für die Kapselung gegeben habe.
Dann hättest du eine saubere Lösung gehabt, die auch dann durch korrekte Bindung ohne Probleme angezeigt werden kann.

Dein aktueller Ansatz ist milde gesagt Schwachsinn.
Du machst aus einer Collection Klasse jetzt einen Container für einen Container mit einer internen Collection.
Das entbehrt jeder Grundlage eines sauberen Klassen Designs und bricht auch mit dem eigentlichen Sinn einer Ableitung von List<T>.

Du hast vorsätzliche alle Ratschläge ignoriert und sogar grundlegende Design Konzepte über Bord geworfen.
Dann hast du uns auch noch mit "vereinfachten" Pseudo Code in die falsche Richtung verwiesen.
Ich denke, du bist hier definitiv falsch wenn du so deine Probleme lösen willst!
Den damit verbrennen wir unsere Zeit mit einem Problem, was du selbst mit solchen "Lösungen" am ende hinsaust.

Nachtrag:
@Palladin007
Diese Lösung wäre auch noch gangbar, wobei ich aber in dem Fall des TE keinen Grund für eine Ableitung sehe, wenn man ein sauberes Klassen Design hat.
Am Ende reicht eigentlich eine saubere Container Klasse für die Member Liste.

T-Virus

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von T-Virus am 13.08.2019 22:11.

13.08.2019 22:08 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 12.901
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von Palladin007:
Oder:

C#-Code:
public class TeamMemberList : IList<string>
{
    private readonly IList<string> _inner;
}

Du machst hier eine Implementierung mit dem Innenleben eines Wrappers.
Man müsste ja alle Methoden selbst implementieren, wobei Du damit einfach List<T> neu entwickeln würdest.
Das macht wenig sinn.

Zitat von T-Virus:
Den damit verbrennen wir unsere Zeit mit einem Problem, was du selbst mit solchen "Lösungen" am ende hinsaust.

So würde ich das jetzt nicht formulieren, denn kein Helfer ist gezwungen zu antworten.
Mit dem anderen Teil, dass Ratschläge ignoriert und Konzepte über Bord geworfen wurden; damit hast natürlich Recht.
13.08.2019 22:10 Beiträge des Benutzers | zu Buddylist hinzufügen
Palladin007 Palladin007 ist männlich
myCSharp.de-Mitglied

Dabei seit: 03.02.2012
Beiträge: 1.174
Entwicklungsumgebung: Visual Studio 2017
Herkunft: NRW


Palladin007 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Die Implementierung macht VisualStudio automatisch, Aufwand wäre das also keiner - zumindest solange Man mit einer halbwegs aktuellen VisualStudio-Version arbeitet.

Wenn man bestimmte Sonderanforderungen hat, kann das unter Umständen hilfreich sein. Ob es Sinn macht, steht dabei natürlich auf einem anderen Blatt, aber es ist definitiv eine mMn. legitime Option.
13.08.2019 22:15 Beiträge des Benutzers | zu Buddylist hinzufügen
T-Virus T-Virus ist männlich
myCSharp.de-Mitglied

Dabei seit: 17.04.2008
Beiträge: 1.269
Entwicklungsumgebung: Visual Studio, Codeblocks, Edi
Herkunft: Nordhausen, Nörten-Hardenberg


T-Virus ist offline Füge T-Virus Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

@Abt
War etwas harsch formuliert, aber wenn man sich eben die Mühe schon gemacht hat und dann die Ratschläge trotz entsprechender Hinweise ignoriert werden, dann bin ich auch etwas gereizt.
Gerade wenn man häufig Code sieht, der Kraut und Rüben ist, dann ist man nicht begeistert wenn man trotz guter Ratschläge die Leute nicht dazu bekommt sauberen Code zu schreiben.

Das frustriert leider immer etwas, wenn man Jahre lang Software entwickelt und sich manche Leute scheinbar sehr Oberflächlich damit beschäftigen.

Aber zurück zum Thema.
Ich kann nur hoffen, dass der TE die Lösung nochmal überarbeitet um seinen Code sauber zu bekommen und diese Ableitung verwirft.

@Palladin007
In diesem Fall würde ich sagen, ist es keine sinnvolle Option.
Das Grundproblem des TE ist scheinbar generelle Grundlegende Konzepte zu verstehen und zu nutzen.
Das eigentliche Problem lässt sich auch am Code erkennen.
Hier würde ein sauberes Klassen Design solche Ansätze sogar überflüssig machen.
Es gab in meinen 10 Jahren als .NET/C# Entwickler bisher keinen driftigen Grund überhaupt eine Ableitung oder Implementierung eines Framework Interfaches vorzunehmen.
Wozu auch, wenn die bestehenden Collections aus dem Generics Namespace ca. 99,9% der Fälle abdecken.
I.d.R. braucht man einfach nur Listen und diesen Fall deck List<T> vollständig ab.

Auch wenn VS dir die Arbeit abnimmt, so sollte man immer unnötige Interface Implementierungen und Ableitungen vermeiden, wenn diese keinen direkten Mehrwert bieten oder einen konkreten Nutzen erfüllen.
Für die Lösung dieses schon banalen Problems, wäre dies mit Kanonen auf Spatzen schießen.

T-Virus

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von T-Virus am 13.08.2019 22:24.

13.08.2019 22:19 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 12.901
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von T-Virus:
dann die Ratschläge trotz entsprechender Hinweise ignoriert werden, dann bin ich auch etwas gereizt.

Bin ja auch ein Freund direkter und sachlicher Worte; aber spar Dir einfach die Energie für Themen, bei denen der Hilfesuchende Ratschläge offener annimmt :-)
Wenn er Ratschläge nich annehmen mag; dann ist das halt so. Zwingen kann man ihn auch nicht.

Zitat von Palladin007:
Die Implementierung macht VisualStudio automatisch, Aufwand wäre das also keiner - zumindest solange Man mit einer halbwegs aktuellen VisualStudio-Version arbeitet.

Und Tests schreiben wir nicht? ;-)

Ehrlich: solange es keinen wirklichen Bedarf gibt, sollte man eine eigene Collection lassen. Gibt ja kaum ein Fall, der ohne Default-Collections nicht machbar wäre.
Es gibt so viele theoretisch Nachteile sowie realistische Nachteile (viele Schnittstellen akzeptieren leider Implementierungen (List<>), weil die Entwickler verpennt haben IList<T> zu verwenden), dass das kaum ohne Reibungsverluste zu machen ist.
Insbesondere wenn wie hier der Fehler einfach nur die simple Anwendung von OOP Basics und damit Code Architektur ist.
14.08.2019 01:03 Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum
Antwort erstellen


© Copyright 2003-2019 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 19.08.2019 08:08