none
Sinnloser(?) Fehler bei Controls.Add eines FlowLayoutPanels RRS feed

  • Frage

  • Hallo zusammen,

     

    ich schreibe im Moment an einer Klasse, die von FlowLayoutPanel erbt und Drag 'n Drop ermöglichen soll...

    Das funktioniert auch alles. Nun wollte ich es möglich machen, dass man eine Datei darauf ziehen kann, für die dann ein spezieller Button erstellt werden soll, der den Pfad der Datei enthält.

    Das funktioniert auch noch. Nun hat dieser neue FileButton(Meine Button-Klasse, die von Button erbt) aber noch die Standardeigenschaften (er ist zu klein, hat die Falsche Farbe...).

    Um das zu ändern habe ich eine neue Eigenschaft zu meiner "FlowLayoutPanel"-Klasse hinzugefügt, die einen Standard-Button enthält.

    Dann soll dieser Code den fertigen Button "erstellen", der alle Eigenschaften richtig hat.

    '----Code zur Zuweisung aller Eigenschaften----
    'source ist vom Typ FileButton
    'Pfad zwischenspeichern
    Dim FilePath As String = source.FilePath'FilePath ist die Eigenschaft meiner Klasse FileButton, die den DateiPfad enthält
    'StandardButton klonen
    source = _MyControlsModel.Clone
    'Pfad zuweisen
    source.FilePath = FilePath
    'Zu den Controls hinzufügen
    Me.Controls.Add(source)
    
    '----Clone-Funktion der Klasse FileButton----
    Public Function Clone() As FileButton
      Return MemberwiseClone()
    End Function
    

    Der Button hat alle Eigenschaften richtig(soweit ich weiss), aber die .Add-Methode funktioniert nicht.

    Sie bringt den Fehler:"child" ist kein untergeordnetes Steuerelement dieses übergeordneten Elements.

    Das Argument von .Add heisst aber value und auch sonst, ich will das Control ja erst hinzufügen, es sollte ja noch gar nicht untergeornet sein!?

    Wenn etwas unklar ist, bitte Fragen!

    Vielen Dank im vorraus für eure Hilfe!

    Mfg Mathe172

    Mittwoch, 9. März 2011 21:17

Antworten

  • Hallo,

    so richtig Hand und Fuß hat das, was Du da machst allem Anschein nach nicht. Zunächst weist Du source eine neue FileButton Instanz zu, die mit dem FilePath aus dem DragDrop- Vorgang beschickt wird. Danach weist Du Source allerdings eine ganz andere FileButton Instanz zu, nämlich das Ergebnis des fruchtlosen Klon.

    Wie ich bereits geschrieben habe, ist (Memberwise)Clone denkbar ungeeignet für Dein Vorhaben. Aber in der Zeit hättest Du jetzt auch eine eigene Clone Methode für Dein Button Modell geschrieben. Via Reflection wäre ebenfalls ein Ansatzpunkt, wenn man es universeller halten möchte. Quick & dirty:

    Public Class FileButton
      Inherits Button
    
      Public Function Clone() As FileButton
        Dim lClone As New FileButton()
    
        Dim lProperties() As PropertyInfo = Me.GetType().GetProperties(BindingFlags.Public Or _
                                        BindingFlags.Instance)
    
        For Each lProperty As PropertyInfo In lProperties
    
          If lProperty.CanWrite And lProperty.CanRead Then
            If lProperty.Name = "WindowTarget" Then
              Continue For
            End If
    
            lProperty.SetValue(lClone, lProperty.GetValue(Me, Nothing), Nothing)
    
          End If
        Next
    
        Return lClone
      End Function
    End Class
    


    Thorsten Dörfler
    Microsoft MVP Visual Basic
    vb-faq.de
    • Als Antwort markiert Mathe172 Montag, 14. März 2011 20:46
    Montag, 14. März 2011 18:22
    Moderator

Alle Antworten

  • Hallo,

    Um das zu ändern habe ich eine neue Eigenschaft zu meiner "FlowLayoutPanel"-Klasse hinzugefügt, die einen Standard-Button enthält.

    Dann soll dieser Code den fertigen Button "erstellen", der alle Eigenschaften richtig hat.

    [...]
    '----Clone-Funktion der Klasse FileButton----
    Public Function Clone() As FileButton
     Return MemberwiseClone()
    End Function
     

    Der Button hat alle Eigenschaften richtig(soweit ich weiss), aber die .Add-Methode funktioniert nicht.

    so ganz folgen kann ich Deiner Beschreibung nicht. Vor allem ist nicht ersichtlich wo welcher Code zum Einsatz kommt, wo der Button herkommt und wo er hinzugefügt werden soll. MemberwiseClone ist für Dein Vorhaben jedoch gänzlich ungeeignet, denn es entsteht keine echte Kopie des Buttons, was vermutlich auch zu dem von Dir festgestellten Fehler führen wird. Erstelle statt dessen eine neue Instanz des Button und kopiere die notwendigen Eigenschaften.


    Thorsten Dörfler
    Microsoft MVP Visual Basic
    vb-faq.de
    Sonntag, 13. März 2011 19:25
    Moderator
  • Hallo,

    danke erst mal für die Antwort. Ich werde versuchen es besser zu erklären.

    Also, ich habe mehrere Klassen:

    FLP, Inherits FlowLayoutPanel :Mein FlowLayoutPanel mit DragDrop

    FileButton, Inherits Button, Eigenschaft: FilePath(String):Pfad zur vom Button dargestellten Datei

    Jetzt wird etwas per DragDrop auf mein FLP gezogen:

            DragDrop

    Datei----------->MeinFLP

    Vom FLP wird das DragDrop Event verarbeitet. Dort wird in die Variable source wenn möglich das Konvertierte DataObject als FileButton abgelegt:

    source = CType(TryCast(e.Data, DataObject), FileButton)

    Der CType Operator von FileButton schaut so aus:

        Public Shared Narrowing Operator CType(ByVal Value As DataObject) As FileButton
            If Not Value.ContainsFileDropList Then Return Nothing
            Return New FileButton With {.FilePath = Value.GetFileDropList(0)}
        End Operator

    Dann sollte der FilePath dieses Buttons (Var.: source) gespeichert werden und source mit einem Klon des ModelButtons per "source=_MyButtonsModel.Clone" gefüllt werden. Dann soll der FilePath wieder geändert werden (source.FilePath=ZwischenSpeicherPfad)

    Das source-Objekt wird dann per Me.Add(source) zum FLP hinzugefügt. Hier tritt aber der Fehler auf.

    Wie lässt sich das verhindern bzw. wie kann ich einen im Designer veränderten FileButton als "Vorbild" für meine Dynamisch erstellten FileButtons benutzen ohne jeweils alle veränderten Eigenschaften zu kopieren und "manuell" zu ändern?

    Ich hoffe ich habe es verständlicher erklärt.

     

    MfG

    Mathe172

    Montag, 14. März 2011 15:49
  • Hallo,

    so richtig Hand und Fuß hat das, was Du da machst allem Anschein nach nicht. Zunächst weist Du source eine neue FileButton Instanz zu, die mit dem FilePath aus dem DragDrop- Vorgang beschickt wird. Danach weist Du Source allerdings eine ganz andere FileButton Instanz zu, nämlich das Ergebnis des fruchtlosen Klon.

    Wie ich bereits geschrieben habe, ist (Memberwise)Clone denkbar ungeeignet für Dein Vorhaben. Aber in der Zeit hättest Du jetzt auch eine eigene Clone Methode für Dein Button Modell geschrieben. Via Reflection wäre ebenfalls ein Ansatzpunkt, wenn man es universeller halten möchte. Quick & dirty:

    Public Class FileButton
      Inherits Button
    
      Public Function Clone() As FileButton
        Dim lClone As New FileButton()
    
        Dim lProperties() As PropertyInfo = Me.GetType().GetProperties(BindingFlags.Public Or _
                                        BindingFlags.Instance)
    
        For Each lProperty As PropertyInfo In lProperties
    
          If lProperty.CanWrite And lProperty.CanRead Then
            If lProperty.Name = "WindowTarget" Then
              Continue For
            End If
    
            lProperty.SetValue(lClone, lProperty.GetValue(Me, Nothing), Nothing)
    
          End If
        Next
    
        Return lClone
      End Function
    End Class
    


    Thorsten Dörfler
    Microsoft MVP Visual Basic
    vb-faq.de
    • Als Antwort markiert Mathe172 Montag, 14. März 2011 20:46
    Montag, 14. März 2011 18:22
    Moderator
  • Hallo,

    Danke für die Antwort. Ich glaube ich habe genau das gesucht (das mit dem Alle eigenschaften abarbeiten und ändern).

    Nochmals Danke,

    Mathe172

    PS.:Eine Frage hätte ich noch:

    MemberwiseClone ist für Dein Vorhaben jedoch gänzlich ungeeignet, denn es entsteht keine echte Kopie des Buttons, was vermutlich auch zu dem von Dir festgestellten Fehler führen wird.

    Was macht es dann genaugenommen?

    Montag, 14. März 2011 20:47
  • MemberwiseClone ist für Dein Vorhaben jedoch gänzlich ungeeignet, denn es entsteht keine echte Kopie des Buttons, was vermutlich auch zu dem von Dir festgestellten Fehler führen wird.

    Was macht es dann genaugenommen?

    MemberwiseClone erstellt eine flache Kopie Deines .NET Objekts. Dass heißt es werden nur die direkten Member (öffentliche, wie private Felder und Eigenschaften) kopiert. Verweistypen werden nicht kopiert, sondern der Kopie zugewiesen. Bei den Windows Forms Elementen kommt das spezielle Problem hinzu, dass der interne Verweis auf das darunterliegende Window Handle in die neue Instanz kopiert wird, statt ein neues Fenster zu erzeugen. Somit erzeugst Du nur ein neues .NET Objekt, das aber auf das gleiche Windows Fenster/Steuerelement wirkt.

    Thorsten Dörfler
    Microsoft MVP Visual Basic
    vb-faq.de
    Montag, 14. März 2011 21:38
    Moderator