On Event geht nur beim Debuggen

  • Hallo zusammen


    Ich habe folgendes Problem:
    Gemäss dem Vortrag von Bernd Hort im EntwicklerCamp 2006 hab ich eine Klasse erstellt für meine Ansichten. Diese Klasse instanziere ich beim QueryOpen Event in einer Ansicht. In meiner Klasse möchte ich nun alles View-spezifische programmieren. So sieht die Klasse aus:


    Public Class ProUIView As ProUIMultiLanguage

    Public Sub new (Source As NotesUIView, Continue As Variant), ProUIMultiLanguage()

    'Define the Events
    Dim sAlias As String
    sAlias=Source.View.Aliases(0)
    If (sAlias="$L-KeywordOwnerOf") Or (sAlias="$L-KeywordOwner") Or (sAlias="$L-Keyword") Or (sAlias="$L-KeywordObject") Or (sAlias="$L-KeywordLanguage") Or (sAlias="$L-Translation") Then
    On Event QueryOpenDocument From Source Call queryOpenDocumentNotAllowed
    End If
    End Sub


    und der Sub:
    Public Sub queryOpenDocumentNotAllowed(Source As Notesuiview, Continue As Variant)
    Continue=False
    End Sub


    Im QueryOpen Event der Ansicht mache ich nun:
    Set pView = New ProUIView (Source, Continue)


    Nun das Problem: Wenn ich debugge, funktioniert das Ganze wunderbar und der queryOpenDocumentNotAllowed wird aufgerufen. Sobald ich den Debugger ausstelle wird es nicht mehr aufgerufen, sprich das Forumlar wird geöffnet.
    :-?


    Ich habs auf Notes 6.5 und Notes 7 ausprobiert. Bei beiden derselbe Effekt.


    Gruss
    Patrick

  • Du kannst ein OnEvent nicht unter eine Bedingung stellen, weil die Bedingung beim Auftreten des Events nicht abgearbeitet wird. Daß das im Debugger funktioniert, hat etwas damit zu tun, daß dort der EventHandler sein Handle auf den Event behält, die If-Abfrage abarbeitet und beim Eintreffen der Bedingung entdeckt, daß dort das Handle auf den aktuellen Event die Code-Verzweigung erzwingt. Der kompilierte ByteCode tut das natürlich nicht.

  • Also, ich habe deinen Code eben mal ausprobiert:
    Ich habe eine Script Library erstellt, die nur die Klasse ProUIView enthält und die Oberklasse ProUIMultiLanguage aus der Deklaration entfernt.


    Ich habe die Sub queryOpenDocumentNotAllowed als Methode der Klasse implementiert.


    Dann habe ich eine Ansicht erstellt, die die Script Library einbindet und im QueryOpen ein Objekt von ProUIView erstellt.


    Bei mir funktioniert alles wie erwartet! (LN 6.5.4)


    Eine Messagebox in der Sub queryOpenDocumentNotAllowed wird auch ausgegeben.



    LN4ever:
    Deine Erklärung kann ich so nicht nachvollziehen.
    Während des Konstruktors ProUIView.New kann man auf die View-Aliase zugreifen und den Eventhandler für QueryOpenDocument installieren - oder eben nicht.


    Tritt dann später ein QueryOpenDocument-Event auf, wird in dem Moment nachgesehen, ob ein Handler dafür registriert ist oder nicht. Wenn ja, wird er aufgerufen, wenn nicht, dann nicht.
    Und da macht der Debugger - zumindest von der Theorie her - keinen Unterschied.




    Patrick:
    Um diese fest codierte Abfrage in deinem Konstruktor ProUIView.New zu vermeiden (beim späteren Umbenennen einer Ansicht ist nicht offensichtlich, dass es diese Abhängigkeit gibt!), könntest Du entweder eine Unterklasse von ProUIView erstellen, die immer das Öffnen des Dokuments verhindert, oder dem Konstruktor einen weiteren Parameter mitgeben, der in einer Objektvariablen gespeichert wird und im QueryOpenDocument-Handler das Continue beeinflusst.


    Mein Favorit wäre wahrscheinlich die zweite Variante (vermeidet eine weitere Klasse):


    Public Class ProUIView As ProUIMultiLanguage


    Dim ProhibitDocOpening as Boolean


    Public Sub New (Source As NotesUIView, Continue As Variant, ProhibitDocOpening as Boolean), ProUIMultiLanguage()


    Me.ProhibitDocOpening = ProhibitDocOpening


    'Define the Events
    On Event QueryOpenDocument From Source Call queryOpenDocumentNotAllowed
    End Sub


    Public Sub queryOpenDocumentNotAllowed(Source As Notesuiview, Continue As Variant)
    Continue = Not ProhibitDocOpening
    End Sub


    End Class



    Im Normalfall
    Set pView = New ProUIView (Source, Continue, False)


    Bei den Ansichten, wo das Öffnen von Dokumenten verboten sein soll:
    Set pView = New ProUIView (Source, Continue, True)



    So steht in der Ansicht selber, welches Verhalten gewünscht wird - und nicht in einem zentralen Element völlig getrennt und nur über den View-Alias verbunden.



    HTH
    Thomas

  • Sorry - ich hatte übersehen, daß du dort bereits in der Klasse im NEW-Konstruktor bist, sondern hatte es verwechselt mit den benamten StandardEvents, weil ich das häufiger mache:


    ich binde in den Globals einer Ansicht eine Bibliothek ein, die ich aber nur im QUERYOPEN mit einer SUB anspreche - und in dieser Bibliotheks-Sub definiere ich alle weiteren Standard-Events mit OnEvent ... . Das erspart einem das Hinzufügen von Code an mehreren Stellen in jeder Ansicht.


    Sorry und Asche auf mein Haupt. Zu schnell gelesen, zu langsam gedacht.


    Aber vielleicht ist ja auch das für manchen ein kleiner Tipp.

  • LN4ever: Macht nichts. Kein Problem. Der Wille zur Hilfe zählt! :)


    @Deragon: Hab den Fehler nun rausgefunden. Script Libraray als einzelne Klasse extrahiert in einer leeren Datenbank. Siehe da, es funktionierte. Also auf die Suche: Hat's was mit den Master-Klassen zu tun? Nein.
    ...fündig wurde ich dann in der View:
    Ich hatte das "Use" im Globals Teil der Ansicht, und die Variable im Declarations Teil auch im Globals, jedoch hatte ich nicht explizit ein "Option Public" hingeschrieben, nur ein "Option Declare". Anscheinend merkt er sich dann die Events nicht beim Ausführen. Das Verhalten ist zwar eigentlch komisch, weil wenn es ja Private für den "Globals" Teil wäre, dann müsste er mir ja beim Kompilieren reklamieren, weil er dann die objView Klasse gar nicht hätte... :-?


    Danke auch für deinen Tipp! Aber das Problem ist dann, wenn ich es als Paramter beim Instanzieren mitgebe, und ich dann die Klasse später erweitere und z.B. noch mehr Parameter hinzufüge, dann müsste ich ja alle Views wieder auf den neuen Parameter anpassen. Meines Wissens gibt es keinen Default-Wert den man einem Paramter geben kann. Im Sinn von einem optionalen Parameter. Oder lieg ich da falsch?

  • Hallo Patrick,


    wie wäre es dann mit einer Unterklasse, die immer sperrt? Dann könntest du in den Keyword-Ansichten diese Unterklasse verwenden, sonst die globale.


    Andere Idee: Nicht als Konstruktor-Parameter, sondern als Attribut mit Setter (oder Set-Property). Vorgabewert: nicht sperren. In den Ansichten, wo gesperrt werden soll, direkt nach dem Erzeugen des Objekts den Setter aufrufen, um das Attribut zu ändern.


    Beispiel:


    Public Sub SetProhibitDocOpening(ProhibitDocOpening)
    Me.ProhibitDocOpening = ProhibitDocOpening
    End Sub


    Im Normalfall
    Set pView = New ProUIView (Source, Continue)


    Bei den Ansichten, wo das Öffnen von Dokumenten verboten sein soll:
    Set pView = New ProUIView (Source, Continue)
    Call pView.SetProhibitDocOpening(True)



    Das Problem mit dem späteren Hinzufügen von Parametern verstehe ich nicht ganz: Wenn du weitere Parameter hinzufügst, musst du doch sowieso alle Aufrufe anpassen, egal ob du ProhibitDocOpening als Parameter aufnimmst oder nicht?!?



    HTH Thomas

  • Hallo Thomas.


    hmm...ich möchte eigentlich nicht eine neue Unterklasse machen, ich möchte nicht zu tiefe Klassenstrukturen. Die Idee, dies als Property zu setzen find ich auch gut. Aber dann hab ich ja die Logik wieder in den Ansichten, dh verteilt in Klasse und Ansicht. Aber eigentlich ist doch der Sinn, die Logik nur in der Klasse zu haben. Oder hab ich da den Bernd Hort falsch interpretiert?


    Ja, stimmt mit den Parametern hast du recht. Aber ich hab eigentlich etwas anderes gemeint. Wenn z.B. eine Methode dazukommt "Dokumente dürfen nicht gepastet werden", in bestimmten Views, dann müsste ich für diese Methode wieder einen Parameter hinzufügen, beim Konstruktor. Das hab ich eigentlich gemeint.

  • Die SetProhibitDocOpening ist natürlich eine Methode der ProUIView-Klasse. Ob und wie Objekte dieser Klasse auf ein gesetztes Attribut ProhibitDocOpening reagieren (z. B. das Verhindern eines direkten Öffnens) ist allein Sache der Klasse.


    Nur die Ansicht weiss aber über sich selbst Bescheid. D. h. insbesondere, es ist völlig in Ordnung, dass im Code der Ansicht
    Call pView.SetProhibitDocOpening(True)
    aufgerufen wird (oder eine Subklasse instanziiert wird statt der ProUIView-Klasse).


    Die Alternative wäre, dass die ProUIView-Klasse ALLE Ansichten kennt, auf die sie besonders reagieren soll. Das wiederspricht aber ganz stark dem Prinzip der Kapselung, weil sie ganz viel "Wissen um ihre Umwelt" haben müsste.


    Außerdem müsstes du dann bei weiteren Ansichten immer wieder die Klasse ändern. Nicht besonders wartungsfreundlich...



    Weitere Attribute, wie ProhibitDocPasting lassen sich trivial ergänzen und haben keinen Einfluss auf den Code in den Ansichten, es sei denn, sie wollen diese Funktion nutzen.



    Ciao
    Thomas

  • Hallo Thomas


    Danke für deine Antworten. Wie du aus anderen Postings vielleicht noch weisst, bin ich momentan am Umstellen auf OO Programmierung, deshalb war ich mir nicht sicher (und hab auch nicht die Erfahrung) ob das so in Ordnung ist. Auf der anderen Seite hab ich mich natürlich auch daran gestört in der Klasse ein if Alias then einbauen zu müssen.


    Aber du hast wohl recht: eine Ansicht weiss am Besten für was sie geeignet ist. Dann ist es legitim ein Set Property zu machen und halt einen Default zu setzen.


    Danke für die Hilfe!