2013-07-26 4 views
0

NSAutlineView를 사용하여 C#/MonoMac 응용 프로그램 내에서 사이드 바를 만들고 Create NSView programatically in Xamarin Studio의 항목을 만드는 데 도움을 얻었습니다. 그러나 이제 아웃 라인보기의 일부 항목을 편집 가능하게 만들었고 물론 항목을 편집하고 조치를 취할 때 (기본 모델을 편집하거나 특별 "새 항목 만들기"항목을 편집 한 경우 새 항목을 작성)를 원합니다.프로그래밍 방식으로 생성 된 NSView의 이벤트 수신

항목을 두 번 클릭하거나 Return 키를 눌러 편집 할 수 있습니다. 그러나 항목이 내 코드에서 편집 된 시간을 감지하는 방법을 알아낼 수 없습니다. 내 NSOutlineViewDataSource에서 CommitEditing을 재정의하려고 시도했으며 내 NSOutlineViewDelegate에서 CommitEditing 및 ShouldEditTableColumn을 모두 재정의했습니다. 이들 중 어느 것도 불려지지는 않습니다.

나는 또한 내 NSOutlineViewDelegate.GetView 메서드에서 MakeView를 호출 할 때 얻을 수있는 뷰의 하위 뷰인 NSTextField에 대한 EditingEnded에 이벤트 처리기를 연결하려고 시도했다. 그러나 이로 인해 응용 프로그램이 중단됩니다. 또한 NSTextField의 대리자를 설정하려고 시도 할 때 충돌이 발생하고 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:]: 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 
) 
+0

난 당신이 MakeView 내 NSTextField있는 조작 할 수 있어야한다 생각합니다. 당신이 얻은 충돌은 무엇입니까? – TheNextman

+0

충돌 예를 추가했습니다. 그러나 서식은 글꼴 크기에 미친 것처럼 보입니다. :/ –

+0

스트레칭이지만, 익명 처리기를 사용하는 대신 이벤트 ('오래된'방식)를 처리하는 메서드를 선언하십시오. – TheNextman

답변

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; 
      } 
     } 
+0

백그라운드 스레드를 소개 할 때까지 코드가 정상적으로 작동합니다. 그런 다음 충돌합니다. 내 응용 프로그램은 특히 시작할 때 백그라운드에서 무거운 작업을 수행 한 다음 인터페이스에 대한 업데이트를 위해 GUI 스레드를 호출하는 등 많은 스레드가 있습니다. 나는 그것이 단지 충돌을 일으키는 스레딩인지 아니면 GUI 프로젝트에서 참조하는 다른 어셈블리에 상주한다는 사실을 확신하지 못합니다. –

+0

어셈블리 사용시 문제가 없어야합니다. 이 문제를 간단하고 재현 할 수있는 예제로 추출 할 수 없다면이 문제에 대한 도움을 찾기가 어려울 것입니다. – TheNextman

+1

그래, 나는 크래시를 소개하는 코드를 계속해서 좁힐 것이다. 나는 해결책/설명이나 그것을 재현 할 수있는 간단한 예를 들고 올 것이다. –