Hilfsklasse für "Parts" für ein Control

  • VB.NET

Es gibt 25 Antworten in diesem Thema. Der letzte Beitrag () ist von Gather.

    Hilfsklasse für "Parts" für ein Control

    Hallo liebe Community,
    ich teste gerade ein bisschen mit einem neuen Control herum.

    Ich habe zwei Klassen das Control an sich und ein ControlPart. Der Controlpart hat die Properties, Name, Color und Value.
    Später werden mit Hilfe dieser Parts etwas gezeichnet. (Je nach dem wie viele Parts vorhanden sind, desto mehr wird gezeichnet.)

    Nun habe ich eine Frage, undzwar, wie speichere ich am Besten diese Parts ab?

    Danke im Vorraus.
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Gather“ ()

    XML oder JSON-Datei? Oder ne ganz normale Textdatei, ganz einfach!
    Oder wie Gonger sagt, über Serialisierung.
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Möglicherweise genügen da Settings, zumal man die direkt an Properties von Controls binden kann.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Nein soetwas möchte ich nicht.
    Besonders nicht die Methode von Trade.

    Serialisierung werde ich mir mal ansehen.
    Wie sieht es eigentlich mit der Methode aus die @Artentus für sein Control (die Paths) benutzt?
    [VB 2012] Erstellen eines einfachen Tracker-Controls
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    Hi
    wie genau wird das Control organisiert? Ggf. genügt ein <System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Content)>-Attribut auf der Liste - oder aber du erzeugst deine eigene Datenbindung, sofern es sowas gibt. Sofern nötig kannst du auch deinen eigenen CodeDomSerializer verwenden (dazu System.Design.dll einbinden, Verwendung gibt's im Internet und ich könnte dir dabei auch helfen).
    Settings, "normale" Serialisierung/Formattierung, etc. sind bei Controls eher nicht gefragt. Das sollte man direkt im Designer-Code bereitstellen. Was sind'n das für ControlParts überhaupt?

    Gruß
    ~blaze~
    Control-Parts ist ein relativ schlechter Ausdruck.
    Ich erkläre deshalb nochmals neu:

    Ich habe erst mal meine Haupt-Klasse, die Control-Klasse die das ganze Zeichnen etc. übernimmt. (Es handelt sich hierbei um ein Torten-Diagramm-Chart-Control).
    Die zweite Klasse definiert ein neues Tortenstück, und gibt gleichzeitig die Möglichkeit pro Tortenstück die Farbe, den Namen, bzw. den Wert festzulegen (uvm.)

    Nun will ich das man so neue Tortenstücke zum Diagramm hinzufügen kann:

    VB.NET-Quellcode

    1. Dim part as New PieChartPart
    2. p.Name = "Teil1"
    3. p.Color = Color.Green
    4. p.Value = 50
    5. PieChart.Parts.add(p)


    Wie kann ich das am sinnvollsten bewerkstelligen?
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    Das einfachste wäre, eine Klasse von System.Collections.ObjectModel.Collection(Of T) erben zu lassen und die Member InsertItem, RemoveItem, etc. zu überschreiben und Notifications an das Control zu senden - oder eben ObservableCollection, was aber eher WinForms-Control-untypisch ist. Das Weiterleiten kannst du z.B. über Friend-Methoden, die du auf dem Control definierst, durchführen. Anschließend setzt du das oben gepostete Attribut auf einer im Control definierten Items-Property. Beim Initialisieren des Controls erzeugst du die Instanz der vorhin von dir definierten Collection und übergibst ihr im Konstruktor die Instanz des Controls selber. So kannst du die Friend-Methoden aufrufen, sobald InsertItem, usw. aufgerufen werden (folglich heißen die Methoden dann eben SubmitOnItemInserted(ByVal index As Integer, ByVal item As PieChartItem), usw.). Jede der Friend-Methoden ruft eine zugehörige Methode auf, die als Protected Overridable deklariert wird (könnten auch nur OnItemAdded und OnItemRemoved sein, da SetItem und ClearItems das gleiche machen. Für ClearItems rufst du btw. eine ItemsClearing- und ItemsCleared-Methode auf, sodass man vor dem Löschvorgang noch auf die Items zugreifen kann).
    In der OnItemsAdded- und OnItemsRemoved-Methode reagierst du dann auf Änderungen am Control und invalidierst es ggf.
    Der Designer sollte dir dann pro PieChartItem entsprechenden Code im Designer generieren.

    Gruß
    ~blaze~
    Ach so, es geht dir gar nicht ums Speichern, sondern darum, die "Hilfsklassen" (so nenne ich die jetzt mal) dem Control hinzuzufügen. Besser das bitte mal aus, bei Speichern denkt jeder an Speichern in eine Datei.
    Naja, in dem Fall sollte mein Tutorial doch genug Information bieten. In "Fortsetzung 2" wird die Auflistung beschrieben.
    Ich hab mir das schon angesehen, und komm dennoch nicht wirklich weiter.
    Beziehungsweise es tun sich hierbei noch ein paar Fragen auf:

    Nehmen wir an, dies ist meine PieChartPartCollection-Klasse:

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. Option Infer On
    4. Imports System.Collections.ObjectModel
    5. Public Class PieChartPartCollection : Inherits Collection(Of PieChartPart)
    6. Public Event ItemAdded As EventHandler(Of PieChartPartCollectionEventArgs)
    7. Public Event ItemRemoving As EventHandler(Of PieChartPartCollectionEventArgs)
    8. Protected Overrides Sub ClearItems()
    9. For Each _item In Me
    10. RaiseEvent ItemRemoving(Me, New PieChartPartCollectionEventArgs(_item))
    11. Next
    12. MyBase.ClearItems()
    13. End Sub
    14. Protected Overrides Sub InsertItem(index As Integer, item As PieChartPart)
    15. MyBase.InsertItem(index, item)
    16. RaiseEvent ItemAdded(Me, New PieChartPartCollectionEventArgs(item))
    17. End Sub
    18. Protected Overrides Sub RemoveItem(index As Integer)
    19. RaiseEvent ItemRemoving(Me, New PieChartPartCollectionEventArgs(Me(index)))
    20. MyBase.RemoveItem(index)
    21. End Sub
    22. Protected Overrides Sub SetItem(index As Integer, item As PieChartPart)
    23. RaiseEvent ItemRemoving(Me, New PieChartPartCollectionEventArgs(Me(index)))
    24. MyBase.SetItem(index, item)
    25. RaiseEvent ItemAdded(Me, New PieChartPartCollectionEventArgs(item))
    26. End Sub
    27. End Class
    28. Public Class PieChartPartCollectionEventArgs : Inherits EventArgs
    29. Private _item As PieChartPart
    30. Public ReadOnly Property Item As PieChartPart
    31. Get
    32. Return _item
    33. End Get
    34. End Property
    35. Public Sub New(item As PieChartPart)
    36. _item = item
    37. End Sub
    38. End Class


    Muss die PieChartPart-Klasse dann einen bestimmen aufbau haben?
    Oder genügt es wenn diese nur das Nötigste beinhaltet: Properties, und New - Sub. (usw.)
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    Ich würde sowas ja nicht über Events lösen, sondern die Änderungen direkt ans Control weiterleiten, wie oben beschrieben. Das ist zwar zusätzlicher Aufwand, aber die Integration ins Control ist praktischer. Außerdem wäre es vorteilhaft, erst nach der Remove-Operation das Event auszulösen. Clearing und Cleared sollte man ebenfalls reporten.

    Gruß
    ~blaze~
    Das passt doch so.
    Der PieCharPart-Klasse kannst du beliebige Eigenschaften und Methoden geben, das hat nichts mit der Collection zu tun. Du musst lediglich dafür sorgen, dass bei Änderungen das Control informiert wird, was ich durch INotifyPropertyChanged gelöst habe, das regelt aber alles das Control selbst, nicht die Collection. Das kannst du dir ja ebenfalls alles genaustens im Tutorial ansehen.

    @~blaze~
    Warum sollten Events nicht funktionieren? Ich finde die machen es einfacher, weil Friend-Member finde ich immer blöd, weils halb gekapselt und halb ungekapselt ist. Da hab ich lieber ein public-Event, darauf kann dann zwar jeder reagieren, aber das ist gar nicht schlimm.
    Und das Event heit "Removing", also gehörts vor das Remove, ansonsten würds ja "Removed" heißen.
    Benötigt die Part-Klasse eine IEnumerable-Schnittstelle, bzw. eine ICollection?
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    Wie würdest du darauf reagieren, wenn du nach dem Remove reagieren möchtest? Das liegt näher, als vor dem Remove. Das item kannst du ja vor dem Remove noch abfragen.
    Die Events gehören eher zum Control, als zur Liste, da das Control damit arbeitet, nicht die Liste selbst. Das GUI und Daten sind in diesem Fall nicht getrennt, insofern ist eben die Collection direkter Bestandteil der GUI und somit wäre es naheliegend, die Events auf dem Control auszuführen, da das eben quasi zuständig für jegliche Verwaltung seiner eigenen "GUI-Daten" ist.

    Btw. einfache Beispiele wären wohl ListBox.Items (wobei das halt auch Datenbindung unterstützt) und Control.Controls.

    Gruß
    ~blaze~
    Gut Danke euch, es funktioniert soweit.
    @~blaze~
    Keine Angst, ich werde mir das nochmal durch den Kopf gehen lassen.

    Dürfte ich hier dennoch noch eine Frage stellen die hier doch vom Thema abweist?
    Wenn ja:

    Wie gesagt, ich habe nun mein PieChart-Control. Man kann via Code soviele Tortenstücke hinzufügen wie es einem beliebt.
    Jedoch, wie führe ich diese Methode dann sinnvoll mit einer "unbekannten" bzw. vareirenden Anzahl an Stücken:

    VB.NET-Quellcode

    1. g.FillPie(brush1, rect, 0, deg1) 'Stück 1
    2. g.FillPie(brush2, rect, deg1, deg2) 'Stück 2
    3. g.FillPie(brush3, rect, deg1 + deg2, deg3) 'Stück 3
    4. g.FillPie(brush4, rect, deg1 + deg2 + deg3, deg4) 'Stück 4


    deg1-4 Sind hierbei die vorher ausgrechneten Winkel:
    Dim deg1 As Single = (Value / TotalValue) * 360
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    Mein Problem ist eher, wie ich auf den letzten Wert dieser Methode kommen soll:
    g.FillPie(Brush, Rectangle, StartAngle, SweepAngle) (SweepAngle).
    Den dass ist immer der Wert der "in der beim nächsten Durchgang" der For-Schleife erst erzeugt wird.
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Gather“ ()

    VB.NET-Quellcode

    1. Dim total As Double
    2. Dim previous As Single = 0
    3. Dim sweep As Single
    4. For Each item As PieDiagramSegment In Items 'Alle Werte aufsummieren
    5. total += item.Value
    6. Next
    7. For Each item As PieDiagramSegment In Items
    8. sweep = CSng(item.Value / total) * 360.0f 'Winkel für aktuelles Item ermitteln
    9. g.FillPie(Brush, Rectangle, previous, sweep)
    10. previous += sweep 'Startwinkel für nächstes Item ermitteln
    11. Next

    so z.B. könnte es gehen.

    Gruß
    ~blaze~

    ~blaze~ schrieb:

    Wie würdest du darauf reagieren, wenn du nach dem Remove reagieren möchtest? Das liegt näher, als vor dem Remove. Das item kannst du ja vor dem Remove noch abfragen.
    Ich möchte ja gerade nicht nach dem Remove reagieren, eben weil ich vor dem Remove noch auf das Item zugreifen könnte. Im ungünstigsten Fall könnte es nämlich so aussehen: Remove - Zugriff - Removed-Event. Dann versuche ich auf ein Item zuzugreifen, das nicht mehr existiert, weil ich noch nicht über dessen Entfernen benachrichtigt wurde. Deshalb feuere ich das Event lieber vor dem Remove als nachher.
    Aber wenn man es mal genau betrachtet ist das sowieso egal, denn Auf ein Control kann man (oder sollte man zumindest) immer nur aus einem Thread aus aufrufen, und deswegen wird das Event und das Remove sowieso immer nacheinander aufgerufen, egal was ich mache.

    ~blaze~ schrieb:

    Das GUI und Daten sind in diesem Fall nicht getrennt
    Das sehe ich aber anders. Warum sollte die Liste zur GUI gehören, nur weil sie ein paar Events feuert? Die Events gehören nicht zum Control, sondern ganz klar zur Liste, denn durch sie teil die Liste mit, wenn sich ihr Inhalt geändert hat. Das ist ja nichts anderes, als bei der ObservableCollection, wenn ich stattdessen diese verwenden würde, dann würde sie deiner Meinung nach auch zur GUI gehören oder was?
    Durch die Events der Liste informiert sich das Control lediglich, wann es sich zu updaten hat. Klar kann man die Events jetzt auch noch durchreichen, damit man auch von außen direkt über das Control über Add und Remove informiert wird, aber das bedeutet doch nicht, dass die Liste keine Events habe darf. Es würde alles nur viel schwieriger machen.