Estoy creando una utilidad para ejecutar en ArcGIS for Desktop usando ArcObjects (9.3.1 SDK) y C # .Net. Mi prototipo implica 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 usará para interactuar con el mapa.
Básicamente quiero seleccionar una capa, seleccionar un campo válido, luego hacer clic en una entidad en el mapa y obtener su valor para el campo elegido. Aquí hay una imagen de la barra de herramientas, si ayuda:
[pregunta redactada casi por completo de aquí abajo]
El problema que tengo es pasar el estado entre las partes nativas de la interfaz de usuario de COM y mis controles personalizados .Net. Por ejemplo, quiero capturar el evento DropDownClosed en el cuadro combinado Capa, armar una lista válida de columnas relativas a esa capa, luego aplicar la lista de nombres de campo (a través de IFields) al cuadro combinado Campos.
Después de aplicar algunos de los comentarios iniciales de RagiYaserBurham y blah238, y fusionarlos con los detalles de esta página , el siguiente controlador de eventos DropDownClosed regresa del cuadro combinado a la barra de herramientas (ICommandBar), pero no entiendo cómo transmitir desde ICommandItem a mi implementación del cuadro combinado Campos 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 lanzo fieldsItem a 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 descriptor de acceso público a mi FieldSelectUC
UserControl para devolver una referencia a su ComboBox; ese simple descriptor de 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í hay un controlador de eventos DropDownClosed que completará el cuadro combinado Campos con todos los campos de la 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 volver a un componente .Net. Realmente aprecio la ayuda de todos los que ofrecieron sugerencias. Muchas gracias. :)
Respuestas:
Según tengo entendido, tiene dos .NET ComboBoxes 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, solo debería poder referirse a ellos por sus nombres de variables (consulte a su diseñador de UserControl para conocer los nombres de sus controles).
Si los dos cuadros combinados están en UserControls separados, intente transmitir
ICommandItem.Command
a su otro UserControl.Consulte este ejemplo en la ayuda 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 sobre este tema: http://forums.esri.com/Thread.asp?c=93&f=993&t=170088
fuente
ICommandItem
a laUserControl
clase que implementé:FieldSelectUC fs = fieldsItem.Command as FieldSelectUC;
ahora puedo ver todos sus accesorios en el depurador. Enormes gracias a ti.C:\Program Files (x86)\ArcGIS\DeveloperKit\SamplesNET\Desktop\GraphicsLayerToolControl\CSharp\GraphicsLayerToolControl2008.sln
) que me ayudó a ponerme en marcha con UserControl y los eventos, pero no pude encontrar la manera de hacer un agujero en .Net desde el control COM. No puedo exagerar lo agradecido que estoy. Sinceramente.Cada vez que hago este tipo de cosas, almaceno los nombres de capa y campo en un conjunto de propiedades estáticas contenido en la barra de herramientas. Luego uso un controlador de eventos de documentos para verificar si las capas se agregan / eliminan de ArcMap o si se cambia el documento. Las propiedades de capa y campo se actualizan cada vez que el usuario las modifica 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:
Barra de herramientas ICommandItem = _iApp.Document.CommandBars.Find ("ArcProject.UI.AngryToolbar", falso, falso);
ICommandItem fieldsItem = (barra de herramientas como ICommandBar) .Find ("ArcProject.UI.FieldSelectUC", falso); IComboBox cbo = (IComboBox) fieldsItem; // Necesita una referencia a ESRI.ArcGIS.SystemUI;
fuente
this
es unaUserControl
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 sé cómo volver a la barra de herramientas para implementar cualquiera de sus sugerencias. (Y en realidad me gusta un poco mejor la idea de estos vars en la barra de herramientas. Probablemente lo haría agregando un captador público a la barra de herramientas que aplique la idea de Ragi). Gracias por tu ayuda continua.this.Parent
sea válido para las interfaces COM, ese es un concepto de .NET / Windows Forms. No desea "atravesar la interfaz de usuario", desea acceder a sus comandos IC por sus ID.Tuve un problema similar con una herramienta personalizada. Tengo un formulario personalizado que se abre con un botón en una barra de herramientas de 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. Pude iniciar la herramienta y manejar el clic en el mapa, pero no pude recuperar el valor de mi formulario, porque la conversión a la herramienta personalizada siempre fallaba. La solución fue usar 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 reside aquí: http://resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/index.html#/Add_in_coding_patterns/0001000000zz000000/
Aquí está el fragmento de código del evento OnClick del botón en el formulario personalizado:
fuente