收听以编程方式创建的NSView中的事件

问题描述 投票:0回答:1

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

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

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

现在我迷路了。好像我已经尝试了一切。

如果要查看代码,请在这里:

模型: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事件时发生的崩溃:

    // ...
    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:]:无法识别的选择器已发送到实例0x16a6c402013-08-02 08:53:32.852 Stoffi [6582:1007]处理键输入时检测到异常。2013-08-02 08:53:32.852 Stoffi [6582:1007]-[__ NSCFType controlTextDidEndEditing:]:无法识别的选择器已发送到实例0x16a6c402013-08-02 08:53:32.863 Stoffi [6582:1007](0 CoreFoundation 0x9966be8b __raiseError + 2191个libobjc.A.dylib 0x98a8f52e objc_exception_throw + 2302 CoreFoundation 0x9966fafd-[NSObject(NSObject)didNotRecognizeSelector:] + 2533 CoreFoundation 0x995b7e87 ___转发___ + 4874 CoreFoundation 0x995b7c32 _CF_forwarding_prep_0 + 505 Foundation 0x93d36e52 __57- [NSNotificationCenter addObserver:selector:name:object:] _ block_invoke_0 + 496 CoreFoundation 0x9962d851 ___CFXNotificationPost_block_invoke_0 + 2577 CoreFoundation 0x99578e8a _CFXNotificationPost + 27948 Foundation 0x93d1f988-[NSNotificationCenter postNotificationName:object:userInfo:] + 929 AppKit 0x972b9926-[NSTextField textDidEndEditing:] + 40510 Foundation 0x93d36e52 __57- [NSNotificationCenter addObserver:selector:name:object:] _ block_invoke_0 + 4911 CoreFoundation 0x9962d851 ___CFXNotificationPost_block_invoke_0 + 25712 CoreFoundation 0x99578e8a _CFXNotificationPost + 279413 Foundation 0x93d1f988-[NSNotificationCenter postNotificationName:object:userInfo:] + 9214 AppKit 0x96fd762b-[NSTextView(NSPrivate)_giveUpFirstResponder:] + 43415 AppKit 0x96fd746f-[NSTextView(NSKeyBindingCommands)insertNewline:] + 58016 libobjc.A.dylib 0x98a9c5d3-[NSObject performSelector:withObject:] + 7017 AppKit 0x96fd714e-[NSResponder doCommandBySelector:] + 9118 AppKit 0x96fd6f83-[NSTextView doCommandBySelector:] + 15219 AppKit 0x97067fe3-[NSTextInputContext doCommandBySelector:] + 12120 AppKit 0x97067f5d-[NSTextInputContext _handleCommand:] + 8421 AppKit 0x97062929-[NSKeyBindingManager(NSKeyBindingManager_MultiClients)interpretEventAsCommand:forClient:] + 200622 AppKit 0x97061db5-[NSTextInputContext handleEvent:] + 129823 AppKit 0x97061825-[NSView interpretKeyEvents:] + 20524 AppKit 0x96fa43b8-[NSTextView keyDown:] + 68025 AppKit 0x971c8af1-[NSWindow sendEvent:] + 743226 AppKit 0x971c390f-[NSApplication sendEvent:] + 427827 AppKit 0x970dd62c-[NSApplication运行] + 95128个AppKit 0x970805f6 NSApplicationMain + 105329 ??? 0x060c9e76 0x0 + 10149029430 ??? 0x060c9c70 0x0 + 10148977631 ??? 0x007beff8 0x0 + 812236032 ??? 0x007bf156 0x0 + 812271033 libmono-2.0.dylib 0x0100be52 mono_jit_runtime_invoke + 72234 libmono-2.0.dylib 0x011a767a mono_runtime_invoke + 17035 libmono-2.0.dylib 0x011aa1f1 mono_runtime_exec_main + 70536 libmono-2.0.dylib 0x011a9401 mono_runtime_run_main + 92937 libmono-2.0.dylib 0x010695e5 mono_jit_exec + 14938 libmono-2.0.dylib 0x0106bb79 mono_main + 960939 Stoffi 0x0000308f主+ 204740 Stoffi 0x00002885开始+ 53)
c# cocoa monomac
1个回答
2
投票

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


编辑添加:

请谨慎做这样的事情:

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

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

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


工作示例:

// 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;
            }
        }
© www.soinside.com 2019 - 2024. All rights reserved.