Closing events in NSWindow

TimLTimL SZMember

Hello,
I'm struggling a bit with closing events in NSWindow class. I need both before and on close. On close was pretty "normal":

this.WillClose += OnFormClosed;

But I also need before event + ability to cancel closing process. I don't know why there is no such event in NSWindow class, but maybe I'm blind. Anyway I tried to create window delegate class with another close event, like this:

    public class TestDelegate : MonoMac.AppKit.NSWindowDelegate
    {
        public override bool WindowShouldClose (MonoMac.Foundation.NSObject sender)
        {
            return false;
        }
    }

and then in NSWindow constructor:

this.Delegate = new TestDelegate();

but that doesn't work. Can you please help with this problem? Thanks

Best Answer

Answers

  • ChrisHamonsChrisHamons Xamurai USForum Administrator, Xamarin Team Xamurai

    I assume you are doing something similar to this: https://gist.github.com/chamons/a552b60d1d776ad3e27c

    If so, you are mixing the C# exposed events and the underlying delegate class. The way that the c# delegates work is by creating an internal delegate and assigning that to the delegate property. However, Cocoa only supports one delegate for a given item. If you switched the order of event registration and delegate assignment, you'd see the other method being called.

    We detect mistakes like this when you build against Unified and throw an exception. I didn't move that check to Classic, for fear of breaking existing user code (since that API was stable, breakages like this are unexpected).

    The solution is that whenever you need to use both a delegate and events, just use the delegate. There is a delegate method for every exposed event (not vise versa for all methods that need to return values).

  • TimLTimL SZMember
    edited May 2015

    I have to say, I'm not sure I understood you completely. I did that change with AwakeFromNib, but it doesn't work.

    I'll be more specific.
    I have programmatically wrote a window, like (I'm on the same app as in previous question actually):

    public class MyWindow : NSWindow
    {
        public MyWindow()
            :base(new RectangleF (0, 0, 100, 100), 
                NSWindowStyle.Closable | NSWindowStyle.Resizable | NSWindowStyle.Titled, NSBackingStore.Buffered, 
                false)
        {
            this.WillClose += OnFormClosed;
            this.MakeKeyAndOrderFront( null );
        }
    }
    
    void OnFormClosed(object sender, EventArgs e)
    {
        //this works!!
    }
    

    No controllers, no delegates.. single file, few lines, pure c#, as simple as possible. Now here, I'd like to add another event. Event before actual closing, where I could call for: "e.Cancel = false;" to cancel closing operation (so OnFormClosed never is even called). So, my question is - what is the best way to achieve that?

    Actually, if it's possible to cancel closing operation in WillClose event - I think, I could live with that. Is it possible?

  • ChrisHamonsChrisHamons Xamurai USForum Administrator, Xamarin Team Xamurai

    @TimL Let me try to explain.

    • The C# events you see exposed are really just us creating a Delegate class for you under the hood and bubbling up the calls as events.
    • You can not mix using those events along with assigning a delegate, as Cocoa only allows one delegate.
    • ShouldClose is not exposed as an event

    Thus, you should move away from using the c# events in this case. Something like:

    https://gist.github.com/chamons/d450d138279ad38df720

  • TimLTimL SZMember

    Well, I've tried this code. Console only printed "Console.WriteLine ("On");" and not "Console.WriteLine ("Should");".

    But AwakeFromNib() is not called in my code. Don't know why actually. Maybe becauseI'm not using xib files? I do "this.Delegate = new TestDelegate();" in my NSWindow constructor.

  • TimLTimL SZMember

    Hmm, I can't edit prev post. I know why I get only "willClose" event and not "shouldClose" one. It's because I'm closing window programmatically via NSWindow.Close(); - not using "red dot".

    Is it possible to catch shouldClose closing window programmatically ?

  • TimLTimL SZMember

    oh, that'd make sense. I'll try that today and let you know if worked

Sign In or Register to comment.