Zwei ähnliche Methoden zusammenfassen?

  • WPF

Es gibt 28 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Zwei ähnliche Methoden zusammenfassen?

    So ein wunderschönes Wochenende allerseits,

    ich habe folgendes Problem:

    Ich habe eine Listbox mit Musiktiteln. Die selektierten Musiktitel sollen auf Knopfdruck entweder zu einer Playlist1 oder einer Playlist2 zugefügt werden. Der User kann dabei mit RadioButtons entscheiden, zu welcher Playlist zugefügt werden soll. Die lstMsusiktitel hat dabei SelectionMode="Multiple". Jetzt könnte ich natürlich das hier machen:

    VB.NET-Quellcode

    1. Private Sub TitelZuPlaylistZufügen()
    2. If Radiobutton1.IsChecked = True Then
    3. For Each item in lstMusiktitel
    4. If item.IsSelected = True Then
    5. Playlist1.Add(item)
    6. Next
    7. Else
    8. For Each item in lstMusiktitel
    9. If item.IsSelected = True Then
    10. Playlist2.Add(item)
    11. Next
    12. End If
    13. End Sub


    Aber geht das vielleicht auch so? (Pseudocode):

    VB.NET-Quellcode

    1. Private Sub TitelZuPlaylistZufügen(WelchePlaylist As Integer)
    2. For Each item in lstMusiktitel
    3. If item.IsSelected = True Then
    4. Playlist(Argument).Add(item)
    5. Next
    6. End Sub


    Dass ich da natürlich wahrscheinlich auch mit DataBinding arbeiten sollte, ist klar. Es soll jetzt in erster Linie um das Vereinfachen der Methode gehen, da ich das an tausend weiteren Stellen in meinem Projekt auch gebrauchen könnte und nicht immer mit If abfragen möchte bzw. (an anderer Stelle des Programms) nicht immer zwei eigentlich identische Methoden schreiben möchte...
    @kafffee Wenn Du die PlayList selbst als Argument übergibst, sieht es so aus (was auch immer Playlist ist):

    VB.NET-Quellcode

    1. Private Sub TitelZuPlaylistZufügen(WelchePlaylist As Playlist)
    2. For Each item In lstMusiktitel
    3. If item.IsSelected Then
    4. WelchePlaylist.Add(item)
    5. End If
    6. Next
    7. End Sub
    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!
    oder so

    VB.NET-Quellcode

    1. Private Sub TitelZuPlaylistZufügen(WelchePlaylist As Playlist)
    2. For Each item In lstMusiktitel.Where(Function(x) x.IsSelected)
    3. WelchePlaylist.Add(item)
    4. Next
    5. End Sub

    oder so

    VB.NET-Quellcode

    1. Private Sub TitelZuPlaylistZufügen(WelchePlaylist As Playlist)
    2. lstMusiktitel.Where(Function(x) x.IsSelected).ToList.ForEach(Sub(x) WelchePlaylist.Add(x))
    3. End Sub

    oder vielleicht so (?, kommt drauf an welchen Typ Playlist hat)

    VB.NET-Quellcode

    1. Private Sub TitelZuPlaylistZufügen(WelchePlaylist As Playlist)
    2. WelchePlaylist.AddRange(lstMusiktitel.Where(Function(x) x.IsSelected).ToArray)
    3. End Sub
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    OK, das sieht für mich schon mal sehr gut aus.
    Reicht für diesen speziellen Fall auch.

    Nun werde ich aber noch sehr viel komplexere Methoden haben. Ungefähr so (wieder Pseudocode):

    VB.NET-Quellcode

    1. Public Sub SpieleTitelAb(Objekt1/2 As Integer)
    2. Player.LadeFile(Playliste(1/2).SelectedIndex.Dateiname)
    3. Player.SpieleFile(Kanal(1/2)) 'Kanal wäre ein Integer)
    4. txtInterpret(1/2).Text = Playliste(1/2).SelectedIndex.Interpret
    5. txtAlbum(1/2).Text = Playliste(1/2).SelectedIndex.Album
    6. txtMusiktitel(1/2).Text = Playliste(1/2).SelectedIndex.Musiktitel
    7. picCoverArt(1/2).Picture = GetPicture(Playliste(1/2).SelectedIndex.Dateiname)
    8. Player.SetEffekt(Kanal(1/2))
    9. usw.......
    10. End Sub


    Playliste wird dann wahrscheinlich eine ObservableCollection(Of MP3FileInfo) oder gar eine Collection View, gebunden an ein DataGrid.

    Ich denke ihr versteht was ich meine. Müsste ich da jedes Objekt einzeln als Argument übergeben, oder kann man das alles in einem Argument übergeben, wie in meinem PseudoCode
    @kafffee Wenn ich das richtig verstehe, genügt da ein (Index As Integer) als Parameter.
    Wenn das so ist, bedenke, dass Indizes in .NET null-basiert sind, also 0|1 und nicht 1|2.
    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!
    Wenn es bei 2 Möglichkeiten bleibt, dann wär es wohl auch so möglich:

    VB.NET-Quellcode

    1. Dim PlayLists As PlayListe() = {Playliste1, Playliste2}
    2. Dim Channels As Kanal() = {Kanal1, Kanal2}
    3. Dim InterpretTextBoxes As TextBox() = {txtInterpret1, txtInterpret2}
    4. Dim AlbumTextBoxes As TextBox() = {txtAlbum1, txtAlbum2}
    5. Dim TitleTextBoxes As TextBox() = {txtMusiktitel1, txtMusiktitel2}
    6. Dim CoverArtPicBoxes As PictureBox() = {picCoverArt1, picCoverArt2}
    7. Public Sub SpieleTitelAb()
    8. Dim CurrentIndex = If(RadioButton1.Checked, 0, 1)
    9. Player.LadeFile(Playlists(CurrentIndex).SelectedIndex.Dateiname)
    10. Player.SpieleFile(Channels(CurrentIndex))
    11. InterpretTextBoxes(CurrentIndex).Text = Playlists(CurrentIndex).SelectedIndex.Interpret
    12. AlbumTextBoxes(CurrentIndex).Text = Playlists(CurrentIndex).SelectedIndex.Album
    13. TitleTextBoxes(CurrentIndex).Text = Playlists(CurrentIndex).SelectedIndex.Musiktitel
    14. CoverArtPicBoxes(CurrentIndex).Picture = GetPicture(Playlists(CurrentIndex)).SelectedIndex.Dateiname)
    15. Player.SetEffekt(Channels(CurrentIndex))
    16. '…
    17. End Sub
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    VaporiZed schrieb:

    VB.NET-Quellcode

    1. Dim PlayLists As PlayListe() = {Playliste1, Playliste2}
    2. Dim Channels As Kanal() = {Kanal1, Kanal2}
    3. Dim InterpretTextBoxes As TextBox() = {txtInterpret1, txtInterpret2}
    4. Dim AlbumTextBoxes As TextBox() = {txtAlbum1, txtAlbum2}
    5. Dim TitleTextBoxes As TextBox() = {txtMusiktitel1, txtMusiktitel2}
    6. Dim CoverArtPicBoxes As PictureBox() = {picCoverArt1, picCoverArt2}
    Diese Initialisierung funktioniert so nicht, da zu diesem Zeitpunkt alle Objekte Nothing sind.
    Das geht erst ab InitializeComponents() oder wie das in WPF funktioniert.
    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!
    Ja, haste recht. Ich meinte auch eher vom Prinzip her. Aber mein geposteter Code bleibt ja damit trotzdem falsch, das ist korrekt.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Ja also vom Prinzip her habt ihr mich richtig verstanden.

    Statt in der Methode würde ich die Arrays aber global deklarieren, denn ich brauche sie programmweit.

    InitializeComponents wird doch beim Erstellen der UI aufgerufen und somit vor jeglichem Code, oder sehe ich das falsch?

    Ich werde mal versuchen, aus dem Code von @VaporiZed doch was rauszukitzeln...

    kafffee schrieb:

    Statt in der Methode würde ich die Arrays aber global deklarieren, denn ich brauche sie programmweit.
    Hab ich doch in meinem Beispielcode gemacht. Nur habe ich sie zusätzlich definiert. Und eben das sollte dann entweder im Form-Konstruktor nach InitializeComponents erfolgen oder z.B. im Form-Load-EventHandler, damit es auch funktioniert und nicht überall Nothing drinsteht.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    RodFromGermany schrieb:

    oder wie das in WPF funktioniert
    Jo, und genau so wie hier gedacht wird, funzt das in Wpf numal nicht.
    In Wpf konzipiert man ein geeignetes Viewmodel und bindeet daran.

    Selbst in WinForms würde ich von sonem Control-Gewurstel abraten.

    Sondern es liegt eine (relationale!) Datenverarbeitung vor, und da braucht man numa ein tragfähiges Datenmodell.



    Ist doch auch bezeichnend:

    kafffee schrieb:

    Dass ich da natürlich wahrscheinlich auch mit DataBinding arbeiten sollte, ist klar.
    guck - er weisses doch selbst.


    kafffee schrieb:

    Es soll jetzt in erster Linie um das Vereinfachen der Methode gehen
    Ja, das ist aber doch in post#3 erledigt

    kafffee schrieb:

    Nun werde ich aber noch sehr viel komplexere Methoden haben
    Sag blos, das langt jetzt doch nicht hin, um durchzukommen...

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @VaporiZed
    Ok na klar haste Recht. Ich meinte damit eher ein Private oder sogar Public...

    ErfinderDesRades schrieb:

    Sondern es liegt eine (relationale!) Datenverarbeitung vor, und da braucht man numa ein tragfähiges Datenmodell.


    Und da genau kommst du ins Spiel. Bevor ich jetzt wieder ins Blaue reinprogrammiere brauch ich noch paar Infos, ums gleich richtig zu machen, dann entfallen auch die Beschwerden über meinen Programmierstil... ;)
    Ich hab mir paar Gedankengemacht und würde folgendermassen an die Sache rangehen:

    Datenmodell: Ich hab ja schon eine Klasse MP3FileInfo. Diese erweitere ich halt noch mit einer Property für das CoverArt und den Intger des Kanals.

    View: Dann binde ich diese Eigenschaften via Instanz (z.B. Dim AbgespielterTitel() As MP3FileInfo) an meine Textboxen, Image, Kanal usw. Wird das folgendenmassen funktionieren?: z.B.: <TextBox Name="txtInterpret" Text="{Binding AbgespielterTitel(0|1)}" DisplayMemberPath="Interpret"/>

    Augenmerk auf das Binding AusgewählterTitel(0|1)!!

    Nun könnte man ja AbgespielterTitel einfach auf die .SelectedRow des DataGrid binden. Soll so aber nicht. Die Änderungen an der UI und das abspielen sollen entweder per Klick auf ein Border mit Canvas drinne (als Icon) (der sich dann die .SelectedRow holt oder aber per Doppelklick auf die Zeile ausgelöst werden, nicht aber, wenn sich .SelectedRow ändert...

    Wie kann ich an diese Sache rangehen?

    Das Datagrid mit der Playlist wird an eine ObersvableCollection of (MP3FileInfo) oder gar eine CollectionView ggebunden sein.

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „kafffee“ ()

    Na es gibt noch mehr Dinge in der Welt als nur Mp3-Dateien. Zum Beispiel PlayLists gibts.
    Und dann muss es Zuordnungen geben, wo je ein Mp3File einer PlayList zugeordnet wird.
    So kann man dieselbe Mp3 mittels mehrerer Zuordnungen mehreren Playlisten zuordnen.

    Aber vernünftig erklären kann ich relationale Datenmodellierung nur mit typDataset: Grundlagen: Relationale Datenmodellierung
    Allenfalls noch anhand einer Datenbank - das wird aber sehr abstrakt.

    AFAIK liegt bei dir weder noch vor, tja, weiss ich auch nicht...

    Vielleicht muss man ein typDataset aufbauen, und dann um jede generierte Klasse ein Viewmodel basteln.
    @VaporiZed

    Genial :thumbsup: Hab deinen Code zum Laufen gebracht... Danke für den Tipp! Das spart mir viel Arbeit und Nerven, dann muss ich nämlich beim Debuggen net die ganze Arbeit doppelt machen... Da würd ich bestimmt irgendwas vergessen oder übersehen. Und sehr viel übersichtlicher wirds. Muss das Ganze halt noch WPF-tauglich machen...

    ErfinderDesRades schrieb:

    AFAIK liegt bei dir weder noch vor, tja, weiss ich auch nicht...


    Ja da muss ich passen. Egal, ich krieg das auch ohne hin... Wenn ich jetzt noch mit Datenbanken oder dergleichen rummache verzettel ich mich sowieso...

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

    Eine Datenbank ist für Playlisten auch nicht notwendig. Hier würde ich völlig simpel einfach eine Klasse in eine XML serialisieren und deserialisieren.

    Vorteil: du kannst es mit eine Dateiendung deiner Wahl abspeichern un in der Registry eine Zuordnung erstellen, dann öffnet Windows eine Playlist automatisch mit deinem Programm. So denke ich willst es zum schluss ja haben.

    Grüße
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    @Nofear23m

    Ja an sowas hatte ich schon gedacht. Hab auch schon eine Methode geschrieben die eine *.m3u-Playlist ins Programm lädt. Ist eigentlich nicht mehr als eine zeilenweise Anhäufung von Pfadnamen in einer normalen Textdatei, zumindest bei der einfachen Version.

    Von (De) Serialisierung hab ich jetzt noch nix gehört, aber wenn ich dich richtig verstehe kann ich da meine Datensätze wie sie sind abspeichern in einem selbst bestimmten Format... Muss ich mich mal schlau machen...
    Ja, du serialisierst eine Klasseninstanz. Dann werde die Werte der Variablen (Properties) als xml Values gespeichert. Nach dem Deserialisieren haste wieder eine Klasseninstanz. Geht mit glaube ich zwei zeilen Code wenn ich nicht irre.

    Grüße
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Ja, serialisieren ist toll.
    Nur ein relationales Datenmodell entsteht dadurch noch nicht.
    Knackpunkt ist, dass es eine Liste von Zuordnungen geben muss.
    Also muss es zuerstmal überhaupt eine Zuordnungs-Klasse geben.
    Also eine Klasse, die kein Mp3Dings ist, und auch keine PlayList, sondern die diese beiden Dinge verknüpft.
    Diese Zuordnungen kann man dann filtern, etwa auf alle Zuordnungen, die einer bestimmten Playlist was zuordnen (nämlich eine Mp3).
    Dieses Filtrat kann man auch ans Gui binden, und zwar so, dass die zugeordneten Mp3 präsentiert werden.

    Wird mit dem Serialisieren dann nicht so ganz trivial, aber ihr kriegt das schon hin.

    ErfinderDesRades schrieb:

    Wird mit dem Serialisieren dann nicht so ganz trivial, aber ihr kriegt das schon hin.

    Doch wird es.

    Wenn man eine Klasse hat, die beides verknüpft (und da hast du Recht, die braucht man zwingend), kann man diese Klasse einfach serialisieren und dann enthält sie auch alles, was in dieser Klasse gespeichert ist - nebst Unterinformationen.

    Was ihr dann nur nicht vergessen dürft: Ihr müsst alle Member (und damit auch Untermember), die darin enthalten sind mit dem Attribute [Serializable] versehen. Dann könnt ihr sie sehr gut serialisieren.