从程序创建的NSView监听事件 [英] Listen to events from programatically created NSView

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

问题描述

我已经在我的C#/ MonoMac应用程序使用NSOutlineView创建一个侧边栏,并获得帮助创建的问题在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 programatically 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).

可以直接编辑项目,无论是双击还是按选择时返回。但我不知道如何检测项目是否在我的代码中编辑。我试图重写我的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,这是一个子视图,当我调用MakeView在我的NSOutlineViewDelegate.GetView方法。但这使应用程序崩溃。我也得到一个崩溃时,我试图设置NSTextField的代理,并在它覆盖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.

现在我失去了。

如果你想看代码,就在这里:

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

使用此代码订阅「已变更」活动时,发生以下情况:

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 对我很好。

编辑以添加:

要小心这样做:

((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天全站免登陆