我已使用NSOutlineView在C#/ MonoMac应用程序内部创建了一个侧边栏,并获得了在问题Create NSView programmatically in Xamarin Studio中创建项目的帮助。但是,现在我已经使大纲视图中的某些项目变为可编辑状态,并且我当然想检测项目何时被编辑并采取措施(编辑基础模型,或者如果编辑了特殊的“创建新项目”,则创建新模型)。
可以通过双击或在选择时按回车键来编辑这些项目。但是我不知道如何检测代码中何时编辑了项目。我尝试覆盖NSOutlineViewDataSource中的CommitEditing,并覆盖NSOutlineViewDelegate中的CommitEditing和ShouldEditTableColumn。这些似乎都没有被调用。
我还尝试将事件处理程序连接到NSTextField的EditingEnded,NSEditField是在NSOutlineViewDelegate.GetView方法中调用MakeView时获得的视图的子视图。但这会使应用程序崩溃。当我尝试设置NSTextField的Delegate并覆盖EditingEnded或TextShouldEndEditing时,也会崩溃。进入编辑模式后,只要按下一个键,就会发生崩溃。
现在我迷路了。好像我已经尝试了一切。
如果要查看代码,请在这里:
这是我使用此代码订阅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)
在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;
}
}