Lösung für die Verwendung vieler Schaltflächen....

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von jan99.

    Lösung für die Verwendung vieler Schaltflächen....

    Moin!

    es war schon etwas schwierig einen passenden Titel für dieses Posting zu finden deshalb jetzt erst einmal worum es geht.

    Im Rahmen eines GIS-Programmes aus dem Hause Autodesk sollen Schaltflächen erstellt werden die jeweils einen eindeutigen Namen haben und dann wiederum einer Funktion zugewiesen werden sollen. Da die Anzahl der Schaltflächen noch nicht final ist muss später erweitert werden - wobei der Erweiterungsumfang möglichst gering und einfach gehalten werden soll.

    Hier einige Code-Passagen, wie es normalerweise ablaufen würde.

    VB.NET-Quellcode

    1. Private WithEvents _BT_ZF_Haltung As Autodesk.Map.IM.Forms.Button = Nothing
    2. Private _Button_ZF_Haltung As String = "$EBLZFHALTUNG"
    3. ...
    4. ''' <summary>
    5. ''' Aktion beim Laden des Dialoges
    6. ''' </summary>
    7. '''
    8. Private Sub Dialog_load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
    9. _MapData = New EBL.MapService.MapData(Me.Document)
    10. Dim ControlName As String
    11. If Me.Dialog.Controls.Contains(ControlName) Then
    12. _BT_ZoomFeatures = CType(Me.Dialog.Controls.ApiItem(ControlName), Autodesk.Map.IM.Forms.Button)
    13. With _BT_ZoomFeatures
    14. .Text = "Zoom ->"
    15. ' deaktivieren der Schaltfläche, wenn die Datenbank schreibgeschützt ist
    16. If Me.Dialog.FeatureClass.ReadOnly Then
    17. .ToolTipText = "Auf Objekte zoomen ..."
    18. End If
    19. _Status_Zoom_Element = True
    20. End With
    21. End If
    22. ZentralButtonControlling()
    23. End Sub
    24. ...
    25. ' hier passiert dann etwas ...
    26. Private Sub Action_ZoomFeatures() Handles _BT_ZoomFeatures.Click
    27. ....
    28. End Sub


    Soweit ist nun einmal das "Gerippe".

    Ich hatte mir nun zuerst überlegt ein Array mit Namen der Schaltflächen (vergleiche _Button_ZF_Haltung) zu erstellen und dann diese in einer Schleife abzuarbeiten. Dafür brauche ich aber eine unterschiedliche Anzahl von Autodesk.Map.IM.Forms.Button-Variablen. Ein Array scheidet aus, weil dieses bei WithEvents wohl nicht geht.

    An dieser Stelle muss ich dann wohl den Weg einschlagen die Namen, nach einem Benennungsprinzip, hard zu codieren - das geht dann auch noch.

    Die Zuweisung der Funktionen aus dem Dialog_load könnte ich dann wieder über eine Schleife lösen.

    Die Handles bei Action_ZoomFeature müssen wiederum zugewiesen werden. Das würde zwar noch in einem Rahmen manuell machbar sein. Dieses würde ich mit AddHandler machen wollen.

    Soweit meine Gedanken zu dem Umfeld. Ich hoffe man kann dieses einigermaßen nachvollziehen.

    Kann mir einer bei der Frage nach dem (halbautomatischen) Anlegen der Buttons weiterhelfen ?

    .... oder hat einer von Euch eine ganz andere Idee ?

    Gruß Jan

    jan99 schrieb:

    WithEvents
    Wenn Du AddHandler verwendest, bist Du auf der guten Seite, insbesondere bei dynamischen Erweiterungen.
    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!

    jan99 schrieb:

    ein Array mit Namen der Schaltflächen
    Alternativ enweder ein Dictionary(Of String, Control) oder eine List(Of Control). Da drin kannst du dann einfach deine Controls WithEvent "adden"

    VB.NET-Quellcode

    1. Dim ctlList As List(Of Button) = new List(Of Button)
    2. Sub AddControls()
    3. ' Schleife oder ähnliches für mehrfaches erzeugen von Buttons
    4. Dim WithEvents ctl As Button
    5. ctl = new ...
    6. 'Eventuell halt noch Handler-Zuweisung wie ROF das bereits beschrieben hat
    7. Me.ctlList.Add(ctl)
    8. 'Schleifen-Ende
    9. End Sub

    Wenn du ein Dictionary verwendest, dann musst du mit .First oder .FirstOrDefault und einem Predicate dir den ensprechenden Button raussuchen, wenn du wieder einen aus der List haben willst
    Bei List ist es zwar nix anderes, nur hast du hier "nur" die .Find()-Methode, die ist aber wesentlich besser und übersichtlicher zu bedienen

    VB.NET-Quellcode

    1. Imports System.Windows.Forms
    2. Module Module1
    3. Dim ctlList As List(Of Control) = New List(Of Control)()
    4. Dim ctlDict As Dictionary(Of String, Control) = New Dictionary(Of String, Control)()
    5. Sub Main()
    6. Dim listCtl As Control = ctlList.Find(Function(ctl)
    7. Return ctl.Name = "Button1"
    8. End Function)
    9. Dim dictCtl As Control = ctlDict.First(Function(entry)
    10. Return entry.Key = "Button1"
    11. End Function).Value
    12. End Sub
    13. End Module


    Lg Radinator
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell
    Moin !

    vielen Dank - das ist ja schon sehr weiterführend.

    Aber bei

    VB.NET-Quellcode

    1. Dim WithEvents ctl As Autodesk.Map.IM.Forms.Button

    bekomme ich auch die Meldung

    "WithEvents" ist bei der Deklaration von lokalen Variablen ungültig.


    Kann einer etwas dazu sagen ?

    Gruß Jan

    jan99 schrieb:

    lokalen Variablen
    Die Deklaration dieser Variable muss aus der Prozedur in die Klasse.
    Wenn Du viele und unbekannte davon hast, geht das nicht, also AddHandler.
    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!
    Moin !

    ich muss noch einmal nachhaken - weil eine Meldung kommt die ich nun gar nicht verstehe.... hier doch zunächst mein aktueller Code:

    VB.NET-Quellcode

    1. Public Class BausacheZoomFeature
    2. Inherits Autodesk.Map.IM.Forms.DialogPlugIn
    3. Dim _MapData As EBL.MapService.MapData
    4. ' Prefix "$EBLZF" wird automatisch vorangestellt
    5. Private _ButtonPrefix As String = "$EBLFZ"
    6. Private _ButtonListe() As String = {"SCHACHT", "HALTUNG"}
    7. Private _ctlList As List(Of Autodesk.Map.IM.Forms.Button) = New List(Of Autodesk.Map.IM.Forms.Button)
    8. Private WithEvents _ctl As Autodesk.Map.IM.Forms.Button
    9. ''' <summary>
    10. ''' Aktion beim Laden des Dialoges
    11. ''' </summary>
    12. '''
    13. Private Sub Dialog_load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
    14. _MapData = New EBL.MapService.MapData(Me.Document)
    15. ' Button erstellen
    16. AddAutodeskMapImFormsButton()
    17. ' diese Funktion steht am Ende des Sub
    18. ZentralButtonControlling()
    19. End Sub
    20. ''' <summary>
    21. ''' Prüfen, ob API-Control vorhanden ist und ggf. einem Adesk-Button zuweisen - Daten werden aus Schleife übernommen
    22. ''' </summary>
    23. Sub AddAutodeskMapImFormsButton()
    24. Dim ControlName As String
    25. For Each ButtonTeilName As String In _ButtonListe
    26. ControlName = _ButtonPrefix & ButtonTeilName
    27. If Me.Dialog.Controls.Contains(ControlName) Then
    28. _ctl = New Autodesk.Map.IM.Forms.Button
    29. _ctl = CType(Me.Dialog.Controls.ApiItem(ControlName), Autodesk.Map.IM.Forms.Button)
    30. With _ctl
    31. .Text = "Zoom ->"
    32. ' deaktivieren der Schaltfläche, wenn die Datenbank schreibgeschützt ist
    33. If Me.Dialog.FeatureClass.ReadOnly Then
    34. .ToolTipText = "Auf Objekte zoomen ..."
    35. End If
    36. End With
    37. AddHandler _ctl.Click, AddressOf Action_ZoomFeatures
    38. Me._ctlList.Add(_ctl)
    39. End If 'contains
    40. Next
    41. End Sub
    42. Private Sub ControlButtons()
    43. End Sub
    44. ''' <summary>
    45. ''' Sammlung der ButtonÜberwachungen
    46. ''' </summary>
    47. Private Sub ZentralButtonControlling()
    48. Dim ButtonStatusZoomFeatures As Boolean = True
    49. If Me.Dialog.Mode <> DialogMode.View Then
    50. ButtonStatusZoomFeatures = False
    51. Else
    52. ButtonStatusZoomFeatures = True
    53. End If
    54. ' hier folgt noch die Enable-Steuerung der Buttons
    55. End Sub
    56. ''' <summary>
    57. ''' Aktion für das Zoomen auf Features
    58. ''' </summary>
    59. Private Sub Action_ZoomFeatures()
    60. 'hier soll etwas passieren...
    61. End Sub



    Jetzt zu der Meldung. In der Zeile

    VB.NET-Quellcode

    1. AddHandler _ctl.Click, AddressOf Action_ZoomFeatures


    wird Action_ZoomFeatures mit folgender Meldung hinterlegt:

    Die Signatur der Private Sub Action_ZoomFeatures()-Methode ist mit dem Delegaten "Delegate Sub EventHandler(sender As Object, e As System.EventArgs)" nicht kompatibel.


    Signatur verstehe ich bisher in der Art und Weise des Aufrufs - z.b. Anzahl der Parameter und deren Typendeklaration.

    ???

    Gruß Jan

    jan99 schrieb:

    nicht kompatibel
    Die Argumente des Handlers stimmen nicht.
    Geh mal mit der Maus auf Click, da müsste er Dir die korrekte Signatur anzeigen.
    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!
    Moin!

    ich bin ja fast begeistert - habe den Code noch etwas umgebaut und schon beim ersten Aufruf ist soweit alles OK !

    Nur stelle ich mir jetzt eine Frage die Funktion Action_ZoomFeatures betreffend an die ich die Aktionen per AddHandler angehängt habe.

    Wer hat beim Aufruf dieser Funktion diese aufgerufen? - ansonsten macht das ganze ja gar keinen Sinn.

    ???

    Gruß Jan

    jan99 schrieb:

    Wer hat beim Aufruf dieser Funktion diese aufgerufen? - ansonsten macht das ganze ja gar keinen Sinn.
    Das Event wird im Endeffekt vom Betriebssystem dadurch aufgerufen, dass der User (Du) mit der Linken oder der Rechten Maustaste auf den Button geklickt hat.
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell

    jan99 schrieb:

    aufgerufen

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Diese Information ist im Parameter sender enthalten.
    Belege die Tag-Property Deines Controls geeignet, die kannst Du dann auslesen und den Sender zuordnen.
    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!
    Moin !

    , dass der User (Du) mit der Linken oder der Rechten Maustaste auf den Button geklickt hat.


    Das ist klar, aber die Funktion muss doch wissen über welche Schaltfläche Action_ZoomFeatures aufgerufen wurde.

    Sonst passiert am Ende immer dasselbe - egal welche Schaltfläche aufgerufen wurde. Oder kann ich irgendwie schon beim AddHandler-Zuweisen schon Parameter mit übergeben?

    Wenn das nämlich versuche, ...

    VB.NET-Quellcode

    1. AddHandler _ctl.Click, AddressOf Action_ZoomFeatures(BP_Key)


    dann bekomme ich die Meldung:

    Der AddressOf-Operand muss dem Namen einer Methode entsprechen (ohne Klammern).

    jan99 schrieb:

    AddHandler
    Danke für das Ignorieren meines posts.
    Teste dies in einem neuen Projekt:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private index As Integer = 0
    2. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    3. Dim btn = New Button
    4. btn.Tag = index
    5. btn.Text = index.ToString
    6. btn.Location = New Point(100, 20 * index)
    7. Me.Controls.Add(btn)
    8. AddHandler btn.Click, AddressOf MyButton_Click
    9. index += 1
    10. End Sub
    11. Private Sub MyButton_Click(sender As Object, e As EventArgs)
    12. Dim ctrl = DirectCast(sender, Button)
    13. Dim tag = ctrl.Tag.ToString
    14. MessageBox.Show(tag)
    15. 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!