聆听以编程方式创建的NSView中的事件 [英] Listen to events from programmatically created NSView

查看:77
本文介绍了聆听以编程方式创建的NSView中的事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用NSOutlineView在C#/ MonoMac应用程序内部创建了一个侧边栏,并获得了帮助创建问题在Xamarin Studio中以编程方式创建NSView 。但是,现在我已经使大纲视图中的某些项目变为可编辑状态,并且我当然想检测项目何时被编辑并采取措施(编辑基础模型,或者如果编辑了特殊的新建项目则创建一个新模型)。

I have created a sidebar inside my C#/MonoMac application using an NSOutlineView and got help creating the items in the question Create NSView programmatically in Xamarin Studio. But now I have made some items in the outline view editable and of course I want to detect when the items are edited and take action (edit the underlying model, or create a new one if a special "Create new" item was edited).

可以通过双击或选择 Return键对项目进行编辑。但是我不知道如何检测代码中何时编辑了项目。我试图在NSOutlineViewDataSource中覆盖CommitEditing,并在NSOutlineViewDelegate中覆盖CommitEditing和ShouldEditTableColumn。这些似乎都没有被调用。

The items can be edited alright, either by double click or pressing Return when it's selected. But I can't figure out how to detect when an item was edited in my code. I have tried to override CommitEditing in my NSOutlineViewDataSource, and override both CommitEditing and ShouldEditTableColumn in my NSOutlineViewDelegate. Neither of these seems to get called.

我还试图将事件处理程序连接到EditingEnded到NSTextField,这是我调用时得到的视图的子视图我的NSOutlineViewDelegate.GetView方法中的MakeView。但这会使应用程序崩溃。当我尝试设置NSTextField的Delegate并覆盖EditingEnded或TextShouldEndEditing时,也会崩溃。进入编辑模式后,只要按下一个键,就会发生崩溃。

I have also tried to hook up an event handler to EditingEnded to the NSTextField which is a subview to the view I get when I call MakeView in my NSOutlineViewDelegate.GetView method. But this makes the application crash. I also get a crash when I try to set the Delegate of the NSTextField and in it override the EditingEnded or TextShouldEndEditing. The crash happens as soon as I press a key after entering edit mode.

现在我迷路了。感觉好像我已经尝试了所有东西。

Now I am lost. It feels as if I've tried everything.

如果您想看一下代码,就在这里:

In case you want to look at the code it's here:

模型: https://code.google.com/p/yet-another-music-application/source/browse/trunk/Player/GUIs/OSX/Models/Navigation.cs

视图控制器: https://code.google.com/p/yet-another-music-application/source/browse/trunk/Player/GUIs/OSX/Views/NavigationViewController .cs

这是当我使用以下代码订阅Changed事件时发生的崩溃:

Here's a crash from when I subscribe to the Changed event using this code:

    // ...
    view = outlineView.MakeView ("DataCell", this);
    ((NSTextField)view.Subviews [1]).Changed += foo;
}

private void foo(object sender, EventArgs e) {
    Console.WriteLine("changed text field.");
};




2013-08-02 08:53:32.851 Stoffi[6582:1007] -[__NSCFType controlTextDidEndEditing:]: unrecognized selector sent to instance 0x16a6c40
2013-08-02 08:53:32.852 Stoffi[6582:1007] Exception detected while handling key input.
2013-08-02 08:53:32.852 Stoffi[6582:1007] -[__NSCFType controlTextDidEndEditing:]: unrecognized selector sent to instance 0x16a6c40
2013-08-02 08:53:32.863 Stoffi[6582:1007] (
    0   CoreFoundation                      0x9966be8b __raiseError + 219
    1   libobjc.A.dylib                     0x98a8f52e objc_exception_throw + 230
    2   CoreFoundation                      0x9966fafd -[NSObject(NSObject) doesNotRecognizeSelector:] + 253
    3   CoreFoundation                      0x995b7e87 ___forwarding___ + 487
    4   CoreFoundation                      0x995b7c32 _CF_forwarding_prep_0 + 50
    5   Foundation                          0x93d36e52 __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 + 49
    6   CoreFoundation                      0x9962d851 ___CFXNotificationPost_block_invoke_0 + 257
    7   CoreFoundation                      0x99578e8a _CFXNotificationPost + 2794
    8   Foundation                          0x93d1f988 -[NSNotificationCenter postNotificationName:object:userInfo:] + 92
    9   AppKit                              0x972b9926 -[NSTextField textDidEndEditing:] + 405
    10  Foundation                          0x93d36e52 __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 + 49
    11  CoreFoundation                      0x9962d851 ___CFXNotificationPost_block_invoke_0 + 257
    12  CoreFoundation                      0x99578e8a _CFXNotificationPost + 2794
    13  Foundation                          0x93d1f988 -[NSNotificationCenter postNotificationName:object:userInfo:] + 92
    14  AppKit                              0x96fd762b -[NSTextView(NSPrivate) _giveUpFirstResponder:] + 434
    15  AppKit                              0x96fd746f -[NSTextView(NSKeyBindingCommands) insertNewline:] + 580
    16  libobjc.A.dylib                     0x98a9c5d3 -[NSObject performSelector:withObject:] + 70
    17  AppKit                              0x96fd714e -[NSResponder doCommandBySelector:] + 91
    18  AppKit                              0x96fd6f83 -[NSTextView doCommandBySelector:] + 152
    19  AppKit                              0x97067fe3 -[NSTextInputContext doCommandBySelector:] + 121
    20  AppKit                              0x97067f5d -[NSTextInputContext _handleCommand:] + 84
    21  AppKit                              0x97062929 -[NSKeyBindingManager(NSKeyBindingManager_MultiClients) interpretEventAsCommand:forClient:] + 2006
    22  AppKit                              0x97061db5 -[NSTextInputContext handleEvent:] + 1298
    23  AppKit                              0x97061825 -[NSView interpretKeyEvents:] + 205
    24  AppKit                              0x96fa43b8 -[NSTextView keyDown:] + 680
    25  AppKit                              0x971c8af1 -[NSWindow sendEvent:] + 7432
    26  AppKit                              0x971c390f -[NSApplication sendEvent:] + 4278
    27  AppKit                              0x970dd62c -[NSApplication run] + 951
    28  AppKit                              0x970805f6 NSApplicationMain + 1053
    29  ???                                 0x060c9e76 0x0 + 101490294
    30  ???                                 0x060c9c70 0x0 + 101489776
    31  ???                                 0x007beff8 0x0 + 8122360
    32  ???                                 0x007bf156 0x0 + 8122710
    33  libmono-2.0.dylib                   0x0100be52 mono_jit_runtime_invoke + 722
    34  libmono-2.0.dylib                   0x011a767a mono_runtime_invoke + 170
    35  libmono-2.0.dylib                   0x011aa1f1 mono_runtime_exec_main + 705
    36  libmono-2.0.dylib                   0x011a9401 mono_runtime_run_main + 929
    37  libmono-2.0.dylib                   0x010695e5 mono_jit_exec + 149
    38  libmono-2.0.dylib                   0x0106bb79 mono_main + 9609
    39  Stoffi                              0x0000308f main + 2047
    40  Stoffi                              0x00002885 start + 53
)


推荐答案

GetView 内的文本字段对我来说很好。问题必须存在于您代码中的其他地方...

Subscribing the event on the text field inside GetView works fine for me. The issue must exist somewhere else in your code...

编辑以添加:

提防执行以下操作:

((NSTextField)view.Subviews [1]).Delegate = new PlaylistNavigationDelegate ();

然后,按照您的原始尝试将事件分配给匿名方法。

And, assigning the event to an anonymous method as per your original attempt.

在这种情况下,一旦控件离开 GetView 的范围,对委托的唯一引用是在非托管方面。 Mono GC无法看到该消息,因此该代表有资格进行收集。当托管引用是从可可粉下面收集到的垃圾时,这可能引起各种问题。

In this case, once control leaves the scope of GetView, the only reference to your delegate is on the unmanaged side. The Mono GC can't see that, and the delegate becomes eligible for collection. This can cause all kind of issues when the managed reference is garbage collected out from underneath Cocoa.

工作示例:

// MainWindowController...

        public override void AwakeFromNib()
        {
            rootNode = new Node(new NSString("Root Node"));

            for(int i = 1; i <=5; i++)
            {
                rootNode.Children.Add(new Node(new NSString("Child Node")));
            }

            sourceList.Delegate = new SourceListDelegate(this);
            sourceList.DataSource = new SourceListDataSource(this);

            base.AwakeFromNib();
        }

        private class SourceListDataSource : NSOutlineViewDataSource
        {
            private MainWindowController controller;

            public SourceListDataSource(MainWindowController controller)
            {
                this.controller = controller;
            }

            public override int GetChildrenCount(NSOutlineView outlineView, NSObject item)
            {
                if(item != null)
                {
                    return (int)((Node)item).Count;
                }

                return (int)controller.rootNode.Count;
            }

            public override bool ItemExpandable(NSOutlineView outlineView, NSObject item)
            {
                if(item == null)
                {
                    return false;
                }

                return !((Node)item).Leaf;
            }

            public override NSObject GetChild(NSOutlineView outlineView, int childIndex, NSObject item)
            {
                if(item == null)
                {
                    return (Node)Runtime.GetNSObject(controller.rootNode.Children.ValueAt((uint)childIndex));
                }

                Node theItem = (Node)item;
                return (Node)Runtime.GetNSObject(theItem.Children.ValueAt((uint)childIndex));
            }

            public override NSObject GetObjectValue(NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item)
            {
                if(item != null)
                {
                    return ((Node)item).Text;
                }

                return new NSString("");
            }
        }

        private class SourceListDelegate : NSOutlineViewDelegate
        {
            private MainWindowController controller;

            public SourceListDelegate(MainWindowController controller)
            {
                this.controller = controller;
            }

            public override bool IsGroupItem(NSOutlineView outlineView, NSObject item)
            {
                return (Node)item == controller.rootNode;
            }

            public override bool ShouldEditTableColumn(NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item)
            {
                return true;
            }

            public override NSView GetView(NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item)
            {
                if(IsGroupItem(outlineView, item))
                {
                    return outlineView.MakeView("HeaderCell", this);
                }

                var view = outlineView.MakeView("DataCell", this);
                var node = (Node)item;

                ((NSTextField)view.Subviews[1]).StringValue = node.Text;
                ((NSTextField)view.Subviews[1]).Changed += HandleChanged;

                return view;
            }

            void HandleChanged (object sender, EventArgs e)
            {
                Console.WriteLine("changed");
            }
        }

        private class Node : NSObject
        {
            private NSMutableArray children = new NSMutableArray();

            public NSMutableArray Children
            {
                get
                {
                    return children;
                }
            }

            public uint Count
            {
                get
                {
                    return Children.Count;
                }
            }

            public bool Leaf
            {
                get
                {
                    return this.Count == 0;
                }
            }

            public NSString Text { get; set; }

            public Node(NSString text)
            {
                this.Text = text;
            }
        }

这篇关于聆听以编程方式创建的NSView中的事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆