ArcObjects (ArcGIS for Desktop 및 C #) : ArcMap COM UI와 사용자 지정 .Net UserControl 개체간에 캐스트하는 방법은 무엇입니까?

ArcObjects (9.3.1 SDK) 및 C # .Net을 사용하여 ArcGIS for Desktop에서 실행할 유틸리티를 생성하고 있습니다. 제 프로토 타입에는 첫 번째 콤보는 TOC에서 레이어를 선택하고 두 번째 콤보는 선택한 레이어에서 필드를 선택합니다.이 도구는지도와 상호 작용하는 데 사용됩니다.

기본적으로 레이어에서 유효한 필드를 선택한 다음지도에서 지형지 물을 클릭하고 선택한 필드에 대한 값을 가져옵니다. 도움이되는 경우 도구 모음 이미지는 다음과 같습니다.

여기에 이미지 설명을 입력하세요.

[여기에서 거의 완전히 다시 말한 질문]

내가 겪고있는 문제는 네이티브 COM UI 부분과 사용자 지정 .Net 컨트롤간에 상태를 전달하는 것입니다. 예를 들어 Layer 콤보 박스에서 DropDownClosed 이벤트를 포착하고 해당 레이어와 관련된 유효한 열 목록을 조합 한 다음 IFields를 통해 필드 이름 목록을 Fields 콤보 박스에 적용합니다.

After RagiYaserBurham 및 blah238의 초기 주석 일부를 적용하고 이 페이지 의 세부 정보와 병합하면 다음 DropDownClosed 이벤트 처리기가 콤보 상자에서 도구 모음으로 다시 이동합니다 ( ICommandBar),하지만 ICommandItem에서 UserControl의 Fields 콤보 상자 구현으로 다시 캐스팅하는 방법을 이해하지 못합니다.

private void layerSelectCBO_DropDownClosed(object sender, EventArgs e) { _completionNotify.SetComplete(); string layerName = (sender as ComboBox).SelectedItem as string; // These two lines are a combination of initial commenter suggestions. ICommandItem toolbar = _iApp.Document.CommandBars.Find("ArcProject.UI.AngryToolbar", false, false); ICommandItem fieldsItem = (toolbar as ICommandBar).Find("ArcProject.UI.FieldSelectUC", false); } 

그래서 .. 이제 I “m here .. fieldsItem을 FieldSelectUC로 어떻게 캐스트합니까?

[ 솔루션 ]

blah238이 제안했듯이 ICommandItem.Command를 사용자 지정 UserControl 구현으로 캐스팅하려고 시도했으며 그게 트릭을 수행했습니다.

먼저, ComboBox에 대한 참조를 반환하기 위해 내 FieldSelectUC UserControl에 공개 접근자를 추가해야했습니다. 이 간단한 접근자는 다음과 같습니다.

// fieldSelectCBO is the name of the combobox control in the design view.. public ComboBox FieldsComboBox { get { return fieldSelectCBO; } } 

수정하면 여기에 “DropDownClosed 이벤트 처리기”가 있습니다.이 이벤트 핸들러는 필드 콤보 상자를 모든 필드로 채 웁니다. 선택한 레이어 :

private void layerSelectCBO_DropDownClosed(object sender, EventArgs e) { _completionNotify.SetComplete(); string layerName = (sender as ComboBox).SelectedItem as string; // get the toolbar.. ICommandItem toolbar = _iApp.Document.CommandBars.Find("ArcProject.UI.AngryToolbar", false, false); // get my fields combo by way of CommandItem.Command.. ICommandItem fieldsCI = (toolbar as ICommandBar).Find("ArcProject.UI.FieldSelectUC", false); FieldSelectUC fieldsUC = fieldsCI.Command as FieldSelectUC; ComboBox fieldsComboBox = fieldsUC.FieldsComboBox; // get the fields for the selected layer.. IFields fields = null; int layerCount = _iDoc.FocusMap.LayerCount; int i; for (i = 0; i < layerCount; i++) { if (_iDoc.FocusMap.get_Layer(i).Name == layerName) { if (_iDoc.FocusMap.get_Layer(i) is FeatureLayer) { fields = (_iDoc.FocusMap.get_Layer(i) as FeatureLayer).FeatureClass.Fields; } } } // Build a list of field names for the combobox items.. List<string> fieldNameList = new List<string>(); if (fields != null) { int fieldCount = fields.FieldCount; int j; for (j = 0; j < fieldCount; j++) { string oneFieldName = fields.get_Field(j).Name; fieldNameList.Add(oneFieldName); } } // Populate the combobox items.. if (fieldNameList.Count > 0) { fieldsComboBox.Items.Clear(); foreach (string fieldName in fieldNameList) { fieldsComboBox.Items.Add(fieldName); } fieldsComboBox.SelectedItem = fieldsComboBox.Items[0]; } else { fieldsComboBox.Items.Add("Error: No fields!"); } } 

이것은 여전히 더티 테스트 베드입니다 (따라서 AngryToolbar).하지만 솔루션은 ICommand 및 IToolControl을 구현하는 확장 된 UserControl에서 시작하는 방법을 보여줍니다. .Net 구성 요소로 다시 드릴 다운합니다. 제안 해 주신 모든 분들의 도움에 감사드립니다. 감사합니다. 🙂

댓글

  • 방법 layerName 변수를 공개 정적 범위로 설정하는 방법에 대해 설명 하시겠습니까?
  • @ artwork21, 좋게 들리지만 ‘ 어떻게 콤보 박스의 인스턴스에 액세스해야할지 잘 모르겠습니다. 툴바에 해당하는 부분이 있습니까? 무슨 뜻인지 알겠습니까? ‘ ‘ 그냥 알지 못하는 단순한 기본 사항이라고 생각합니다.
  • 차이처럼 들립니다. 정확한 질문. ‘ 왜 그렇게해야하는지 잘 모르겠습니다. 필자는 Fields 콤보 상자를 지우고 Layer 콤보를 기반으로 다시 채워야하는 것 같습니다. 레이어 콤보 박스는 문서 이벤트 리스너를 기반으로 채워야합니다.
  • @RichWawrzonek 정확히 맞습니다. 하지만 ‘ 레이어 콤보에서 필드 콤보의 기존 인스턴스를 가져 오는 방법을 잘 모르겠습니다.이 문제를 위해 도구는 두 값을 모두 읽어야합니다.

li>

Answer

내가 이해했듯이 ICommand 및 IToolControl을 구현하는 UserControl에 두 개의 .NET ComboBox가 있습니다. 다른 하나의 콤보 상자 중 하나에 대한 참조를 얻고 싶습니다. 동일한 범위에있는 한 변수 이름으로 참조 할 수 있어야합니다 (컨트롤 이름에 대해서는 UserControl 디자이너를 확인하십시오).

두 콤보 상자가 별도에있는 경우 UserControls를 입력 한 다음 ICommandItem.Command를 다른 UserControl로 캐스팅 해보세요.

몇 가지 예는 9.3 도움말에서이 샘플을 참조하세요. 최근 사용 파일-Command, MultiItem 및 ToolControl

또한 다음은이 문제를 논의하는 ESRI 포럼 게시물입니다. http://forums.esri.com/Thread.asp?c=93&f=993&t=170088

댓글

  • Bingo. 이 줄은 ICommandItem 인스턴스에서 내가 구현 한 UserControl 클래스로 다시 돌아가는 트릭을 수행했습니다. FieldSelectUC fs = fieldsItem.Command as FieldSelectUC; 이제 디버거에서 모든 ‘ 소품을 볼 수 있습니다. 감사합니다.
  • 만세! 저는 ‘ 한동안 애드 인을 독점적으로 사용하고 있었기 때문에 모든 기능이 어떻게 작동하는지 기억하기 위해 오래된 것들을 파헤쳐 야했습니다. 🙂 이런 종류의 작업이 훨씬 더 쉽습니다. 특정 ComboBox 유형이 있고 정적 변수 및 메서드를 사용하여 다른 추가 기능 구성 요소를 참조 할 수 있으므로 10의 추가 기능을 사용하면 유연성이 떨어집니다.
  • 네, 새로운 추가 기능을 통해 확실히 더 쉬워 보였습니다. 이를 조사하면서이 추가 기능과 추가 기능을 찾았지만 구현에 사용할 수없는 ‘입니다. .Net 도움말의 GraphicsLayerToolControl 예제 (내 시스템의 주소는 C:\Program Files (x86)\ArcGIS\DeveloperKit\SamplesNET\Desktop\GraphicsLayerToolControl\CSharp\GraphicsLayerToolControl2008.sln)가 UserControl 및 이벤트 관련 작업을 수행하는 데 도움이되었지만 ‘ COM 컨트롤에서 .Net에 구멍을 뚫는 방법을 찾지 못했습니다. 저는 ‘ 내가 얼마나 감사한지 과장 할 수 없습니다. 감사합니다.

답변

이런 일을 할 때마다 레이어와 필드 이름을 정적 도구 모음에 포함 된 속성 집합입니다. 그런 다음 문서 이벤트 핸들러를 사용하여 ArcMap에서 레이어가 추가 / 제거되었는지 또는 문서가 변경되었는지 확인합니다. 레이어 및 필드 속성은 사용자가 드롭 다운에서 변경할 때마다 업데이트됩니다. ArcMap에서 레이어가 제거되거나 문서가 닫히면 null로 재설정됩니다. 그런 다음 프로그램이 실행되기 전에 null 값을 확인할 수 있습니다.

ICommandItem 인터페이스를 통해 콤보 박스에 대한 참조를 가져옵니다.

ICommandItem toolbar = _iApp.Document.CommandBars.Find ( “ArcProject.UI.AngryToolbar”, false, false);
ICommandItem fieldsItem = (ICommandBar로 도구 모음) .Find ( “ArcProject.UI.FieldSelectUC”, false); IComboBox cbo = (IComboBox) fieldsItem; //ESRI.ArcGIS.SystemUI에 대한 참조가 필요합니다.

댓글

  • +1하면 쉽게 들릴 수 있습니다. 🙂 그러나 내가 가진 문제는 다른 컨트롤의 관점에서 이미 인스턴스화 된 컨트롤의 속성에 액세스하는 것입니다. 도구 모음에 공유 속성을 넣는 아이디어가 마음에 듭니다. 콤보 상자 중 하나의 관점에서 포함하는 도구 모음의 속성을 실제로 읽는 방법을 보여주기 위해 답변을 업데이트 할 수 있습니까? ‘ 왜냐하면 ‘ 기본적으로 제가 ‘ m 이후입니다. 문서 이벤트를 사용하여 TOC 변경을 수신하는 방법을 이미 알고 있으므로 ‘이 측면에 대한 도움이 필요하지 않습니다. 응답 해 주셔서 감사합니다.
  • @elrobis ICommand 자체에 공유 상태를 넣은 다음 (항상 하나의 인스턴스 만 있기 때문에) 컨트롤이

    help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/ …

  • Ragi는 권리. COM 도구 모음을 사용하고 있으므로 콤보 상자의 uid를 ICommandBar.Find 메서드에 전달하여 참조를 얻을 수 있습니다. 그의 링크는 모든 것을 설명합니다.
  • 저는 Ragi ‘의 아이디어도 좋아합니다. 그래도 내가 놓친 근본적인 것이 있습니다. 예를 들어 다음 줄은 null 도구 모음을 반환합니다 (여기서 this는 레이블과 콤보 상자가있는 UserControl 임). ICommandBar toolbar = this.Parent as ICommandBar; ‘ 저를 죽이는 것은 이러한 종류의 기본적인 UI 개체 순회입니다. 저는 ‘ 툴바로 돌아가서 제안 사항을 구현하는 방법을 모릅니다. (실제로 툴바에있는 이러한 변수에 대한 아이디어가 조금 더 마음에 듭니다. 저는 ‘ Ragi를 적용하는 툴바에 공개 getter를 추가하여이를 수행 할 것입니다 ‘의 아이디어). 지속적인 도움을 주셔서 감사합니다.
  • this.Parent가 COM 인터페이스에 유효하지 않다고 생각합니다. 즉 .NET / Windows Forms 개념. ‘ ” UI를 횡단하지 않고 ” ID 별 ICommands.

Answer

사용자 지정 도구에서 비슷한 문제가 발생했습니다. ArcGis 10.x에서 AddIn-Toolbar의 버튼으로 열리는 사용자 지정 양식이 있습니다. 이 양식에는 스냅이 포함 된지도에서 클릭의 좌표를 검색해야하는 버튼이 있습니다. 도구를 시작하고지도에서 클릭을 처리 할 수 있었지만 사용자 지정 도구에 대한 캐스트가 항상 실패했기 때문에 값을 내 양식으로 되돌릴 수 없었습니다. 해결책은 ESRI.ArcGIS.Desktop.AddIns의 AddIn을 사용하는 것이 었습니다. 이를 통해 내 사용자 지정 도구의 모든 속성과 방법에 쉽게 액세스 할 수있었습니다. ESRI 문서는 다음 위치에 있습니다. http://resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/index.html#/Add_in_coding_patterns/0001000000zz000000/

다음은 OnClick-의 코드 스 니펫입니다. 사용자 정의 양식의 버튼 이벤트 :

//DESCRIPTION: //Connect a tool embedded in a Windows Form with the ArcGIS Application Framework. ESRI.ArcGIS.esriSystem.IUID UIDCls = new ESRI.ArcGIS.esriSystem.UIDClass(); UIDCls.Value = "MyNamespace_MyCustomTool"; IDocument actDoc = (IDocument)ArcMap.Document; //Finding the customTool ESRI.ArcGIS.Framework.ICommandItem commandItem = actDoc.CommandBars.Find(UIDCls, false, false); if (commandItem == null) { return; } //This cast would fail: //MyCustomTool_Class actCustomTool2 = (MyCustomTool_Class)commandItem.Command; MyCustomTool_Class actCustomTool = AddIn.FromID<MyCustomTool_Class (ThisAddIn.IDs.MyCustomTool); actCustomTool.actFrm = this; ArcMap.Application.CurrentTool = commandItem; 

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다