ArcObjects (ArcGIS for Desktop y C #): ¿Cómo transmitir entre la interfaz de usuario COM de ArcMap y mis objetos UserControl personalizados .Net?

Estoy creando una utilidad para ejecutar en ArcGIS for Desktop usando ArcObjects (9.3.1 SDK) y C # .Net. Mi prototipo involucra una barra de herramientas con dos cuadros combinados y una herramienta. El primer combo selecciona una capa en la tabla de contenido y el segundo selecciona un campo de la capa seleccionada. La herramienta se utilizará para interactuar con el mapa.

Básicamente, quiero seleccionar un capa, seleccione un campo válido, luego haga clic en una característica en el mapa y obtenga su valor para el campo elegido. Aquí hay una imagen de la barra de herramientas, si ayuda:

ingrese la descripción de la imagen aquí

[pregunta casi completamente redactada de aquí para abajo]

El problema que tengo es pasar el estado entre las partes nativas de la interfaz de usuario COM y mis controles personalizados .Net. Por ejemplo, quiero capturar el evento DropDownClosed en el combobox Layer, ensamblar una lista válida de columnas relativas a esa capa, luego aplicar la lista de nombres de campo (vía IFields) al combobox Fields.

Después aplicando algunos de los comentarios iniciales de RagiYaserBurham y blah238, y fusionándolos con detalles de esta página , el siguiente controlador de eventos DropDownClosed va del cuadro combinado a la barra de herramientas ( ICommandBar), pero no entiendo cómo convertir desde ICommandItem a mi implementación del cuadro combinado Fields en un UserControl:

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); } 

Entonces … ahora que Estoy aquí … ¿cómo puedo convertir fieldsItem en FieldSelectUC?

[ La solución ]

Como sugirió blah238, intenté enviar ICommandItem.Command a mi implementación personalizada de UserControl y eso funcionó.

Primero, tuve que agregar un acceso público a mi FieldSelectUC UserControl para devolver una referencia a su ComboBox; ese simple acceso se ve así:

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

Con esa modificación en su lugar, aquí «un controlador de eventos DropDownClosed que llenará el cuadro combinado Fields con todos los campos del capa seleccionada:

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!"); } } 

Esto sigue siendo un banco de pruebas sucio (de ahí AngryToolbar). Pero la solución muestra cómo comenzar desde un UserControl extendido que implementa ICommand e IToolControl y profundice en un componente .Net. Realmente aprecio la ayuda de todos los que ofrecieron sugerencias. Muchas gracias. 🙂

Comentarios

  • Cómo acerca de hacer que su layerName variable sea un ámbito estático público?
  • @ artwork21, eso suena bien, pero ‘ todavía no estoy seguro de cómo acceder a la instancia de cualquiera de los combobox desde ¿Su contraparte en la barra de herramientas? ¿Sabes a qué me refiero? Sospecho que ‘ es una cosa fundamental simple que ‘ simplemente no conozco.
  • Esto suena como una diferencia pregunta actual. No ‘ no tengo claro por qué necesita hacer eso. Me parece que el cuadro combinado de Campos debería borrarse y volverse a llenar según el combo de Capa. El cuadro combinado de capas debe completarse en función del detector de eventos del documento.
  • @RichWawrzonek que es exactamente correcto. Pero ‘ no estoy seguro de cómo llegar a la instancia existente del combo Fields desde el combo Layers. Para el caso, la herramienta necesita leer ambos valores.

Respuesta

Según tengo entendido, tiene dos ComboBoxes .NET en un UserControl que implementa ICommand e IToolControl, y desea obtener una referencia a uno de los cuadros combinados del otro. Siempre que estén en el mismo ámbito, debería poder referirse a ellos por sus nombres de variable (verifique en su diseñador de UserControl los nombres de sus controles).

Si los dos cuadros combinados están separados UserControls, luego intente transmitir ICommandItem.Command a su otro UserControl.

Vea este ejemplo en la ayuda de 9.3 para ver algunos ejemplos: Archivos usados recientemente: Command, MultiItem y ToolControl

También aquí hay una publicación en el foro de ESRI que discute este tema: http://forums.esri.com/Thread.asp?c=93&f=993&t=170088

Comentarios

  • Bingo. Esta línea funcionó para volver de la instancia de ICommandItem a la UserControl clase que implementé: FieldSelectUC fs = fieldsItem.Command as FieldSelectUC; Ahora puedo ver todos sus ‘ accesorios en el depurador. Muchísimas gracias a ti.
  • ¡Hurra! ‘ he estado usando complementos exclusivamente por un tiempo, así que tuve que buscar en algunas cosas antiguas para recordar cómo funcionaba todo 🙂 Este tipo de cosas es mucho más fácil (aunque es cierto que menos flexible) con complementos en 10, ya que hay un tipo ComboBox específico y puede hacer referencia a otros componentes complementarios con variables y métodos estáticos.
  • Sí, definitivamente parecía más fácil a través de los nuevos complementos. Al investigar esto, encontré complementos esto y complementos aquello, pero simplemente no estaban ‘ t disponibles para mi implementación. El ejemplo de GraphicsLayerToolControl en la ayuda de .Net (en mi sistema esa dirección es C:\Program Files (x86)\ArcGIS\DeveloperKit\SamplesNET\Desktop\GraphicsLayerToolControl\CSharp\GraphicsLayerToolControl2008.sln) que me ayudó a ponerme en marcha con UserControl y cosas de eventos, pero no pude ‘ No averigüe cómo hacer un agujero a través de .Net desde el control COM. No puedo ‘ exagerar lo agradecido que estoy. Atentamente.

Responder

Siempre que hago este tipo de cosas, almaceno los nombres de las capas y los campos en un conjunto de propiedades contenido en la barra de herramientas. Luego uso un controlador de eventos de documento para verificar si se agregan / eliminan capas de ArcMap o si se cambia el documento. Las propiedades de la capa y el campo se actualizan cada vez que el usuario las cambia en el menú desplegable. Si la capa se elimina de ArcMap o el documento se cierra, se restablecen a nulo. Luego, puede verificar los valores nulos antes de que se ejecute su programa.

Obtenga una referencia al cuadro combinado a través de la interfaz ICommandItem:

ICommandItem toolbar = _iApp.Document.CommandBars.Find («ArcProject.UI.AngryToolbar», false, false);
ICommandItem fieldsItem = (barra de herramientas como ICommandBar) .Find («ArcProject.UI.FieldSelectUC», falso); IComboBox cbo = (IComboBox) fieldsItem; // Necesita una referencia a ESRI.ArcGIS.SystemUI;

Comentarios

  • +1 lo haces sonar tan fácil. 🙂 Pero el problema que tengo es acceder a las propiedades de un control ya instanciado desde el punto de vista de cualquier otro control. Me gusta su idea de poner sus propiedades compartidas en la barra de herramientas, ¿podría actualizar su respuesta para mostrar cómo puedo realmente leer las propiedades de la barra de herramientas que las contiene desde el punto de vista de uno de los cuadros combinados? ‘ Porque eso ‘ es básicamente lo que ‘ m después. Ya sé cómo usar eventos de documentos para escuchar cambios en la TOC, por lo que no ‘ necesito ayuda con ese aspecto. Gracias por su respuesta.
  • @elrobis También puede poner el estado compartido en el ICommand mismo (ya que siempre habrá una sola instancia) y luego hacer que los controles obtengan un identificador del comando a través de help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/…
  • Ragi es derecho. Como está utilizando la barra de herramientas COM, puede simplemente pasar el uid de su cuadro combinado al método ICommandBar.Find para obtener una referencia. Su enlace lo explica todo.
  • También me gusta la idea de Ragi ‘. Sin embargo, hay algo fundamental que me falta. Por ejemplo, esta línea devuelve una barra de herramientas nula (donde this es un UserControl con etiqueta y cuadro combinado): ICommandBar toolbar = this.Parent as ICommandBar; Es ‘ este tipo de recorrido fundamental de objetos de IU lo que me está matando. No ‘ no sé cómo volver a la barra de herramientas para implementar cualquiera de sus sugerencias. (Y de hecho, me gusta un poco más la idea de estas variables en la barra de herramientas. Probablemente ‘ lo haga agregando un captador público a la barra de herramientas que aplica Ragi ‘ s idea). Gracias por su ayuda continua.
  • No ‘ creo que this.Parent sea válido para interfaces COM, es decir un concepto de .NET / Windows Forms. No ‘ no desea » atravesar la interfaz de usuario «, desea acceder a su IComandos por sus ID.

Respuesta

Tuve un problema similar con una herramienta personalizada. Tengo un formulario personalizado que se abre con un botón en una barra de herramientas AddIn en ArcGis 10.x. En este formulario hay un botón que debe recuperar las coordenadas de un clic en el mapa, incluido el ajuste. Podría iniciar la herramienta y manejar el clic en el mapa, pero no pude recuperar el valor en mi formulario, porque la conversión a la herramienta personalizada siempre fallaba. La solución fue utilizar AddIn de ESRI.ArcGIS.Desktop.AddIns. Con esto, fue fácil acceder a todas las propiedades y métodos de mi herramienta personalizada. La documentación de ESRI se encuentra aquí: http://resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/index.html#/Add_in_coding_patterns/0001000000zz000000/

Aquí está el fragmento de código de OnClick- Evento del botón en el formulario personalizado:

//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; 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *