Estou criando um utilitário para executar no ArcGIS for Desktop usando o ArcObjects (9.3.1 SDK) e o C # .Net. Meu protótipo envolve uma barra de ferramentas com duas caixas de combinação e uma ferramenta. O primeiro combo seleciona uma camada no sumário e o segundo seleciona um campo da camada selecionada. A ferramenta será usada para interagir com o mapa.
Basicamente, quero selecionar uma camada, selecionar um campo válido, clicar em um recurso no mapa e obter seu valor para o campo escolhido. Aqui está uma imagem da barra de ferramentas, se ajudar:
[pergunta quase inteiramente reformulada daqui em diante]
O problema que estou tendo é passar o estado entre as partes da interface do usuário COM nativa e meus controles .Net personalizados. Por exemplo, quero capturar o evento DropDownClosed na caixa de combinação Layer, montar uma lista válida de colunas em relação a essa camada e aplicar a lista de nomes de campos (via IFields) à caixa de combinação Fields.
Após aplicar alguns comentários iniciais de RagiYaserBurham e blah238 e mesclá-los aos detalhes desta página , o seguinte manipulador de eventos DropDownClosed vai da caixa de combinação de volta à barra de ferramentas (ICommandBar), mas não entendo como transmitir a partir de ICommandItem para minha implementação da caixa de combinação Fields em um 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);
}
Então .. agora que estou aqui .. como faço para converter fieldsItem para FieldSelectUC?
[ A solução ]
Como blah238 sugeriu, tentei converter ICommandItem.Command para minha implementação personalizada UserControl e isso foi o que fez.
Primeiro, tive que adicionar um acessador público ao meu FieldSelectUC
UserControl para retornar uma referência à sua ComboBox; esse acessador simples se parece com isso:
// fieldSelectCBO is the name of the combobox control in the design view..
public ComboBox FieldsComboBox { get { return fieldSelectCBO; } }
Com essa modificação, aqui está um manipulador de eventos DropDownClosed que preencherá a caixa de combinação Fields com todos os campos da camada selecionada:
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!");
}
}
Este ainda é um teste sujo (daí o AngryToolbar). Mas a solução mostra como iniciar a partir de um UserControl estendido que implementa ICommand e IToolControl e fazer drill down de volta para um componente .Net. Eu realmente aprecio a assistência de todos que ofereceram sugestões. Muito obrigado. :)
Respostas:
Pelo que entendi, você tem duas .NET ComboBoxes em um UserControl que implementa ICommand e IToolControl e deseja obter uma referência a uma das caixas de combinação da outra. Desde que estejam no mesmo escopo, você deve ser capaz de se referir a eles pelos nomes de variáveis (verifique o designer do UserControl para obter os nomes dos seus controles).
Se as duas caixas de combinação estiverem em UserControls separados, tente transmitir
ICommandItem.Command
para seu outro UserControl.Veja este exemplo na ajuda da 9.3 para obter alguns exemplos: Arquivos usados recentemente - Command, MultiItem e ToolControl
Também aqui está uma postagem no fórum da ESRI que discute esse problema: http://forums.esri.com/Thread.asp?c=93&f=993&t=170088
fonte
ICommandItem
retornar da instância de volta àUserControl
classe que eu implementei:FieldSelectUC fs = fieldsItem.Command as FieldSelectUC;
agora posso ver todos os seus props no depurador. Um tremendo agradecimento a você.C:\Program Files (x86)\ArcGIS\DeveloperKit\SamplesNET\Desktop\GraphicsLayerToolControl\CSharp\GraphicsLayerToolControl2008.sln
) que me ajudou a seguir o UserControl e as coisas de eventos, mas eu simplesmente não conseguia descobrir como fazer um furo no .NET com o controle COM. Não posso exagerar o quanto sou grato. Atenciosamente.Sempre que faço esse tipo de coisa, armazeno os nomes de camada e campo em um conjunto de propriedades estáticas contido na barra de ferramentas. Então eu uso um manipulador de eventos de documento para verificar se as camadas foram adicionadas / removidas do ArcMap ou se o documento foi alterado. As propriedades da camada e do campo são atualizadas sempre que são alteradas no menu suspenso pelo usuário. Se a camada for removida do ArcMap ou o documento for fechado, elas serão redefinidas para nulas. Então você pode apenas verificar valores nulos antes da execução do programa.
Obtenha uma referência à caixa de combinação através da interface ICommandItem:
Barra de ferramentas ICommandItem = _iApp.Document.CommandBars.Find ("ArcProject.UI.AngryToolbar", false, false);
ICommandItem fieldsItem = (barra de ferramentas como ICommandBar) .Find ("ArcProject.UI.FieldSelectUC", false); IComboBox cbo = (IComboBox) fieldsItem; // Precisa de uma referência para ESRI.ArcGIS.SystemUI;
fonte
this
está umUserControl
rótulo e uma caixa de combinação):ICommandBar toolbar = this.Parent as ICommandBar;
é esse tipo de passagem fundamental de objeto da interface do usuário que está me matando. Não sei como voltar para a barra de ferramentas para implementar uma de suas sugestões. (E, na verdade, eu gosto um pouco melhor da ideia desses vars na barra de ferramentas. Eu provavelmente faria isso adicionando um getter público à barra de ferramentas que aplica a ideia de Ragi). Obrigado pela sua ajuda contínua.this.Parent
seja válido para interfaces COM - esse é um conceito do .NET / Windows Forms. Você não deseja "atravessar a interface do usuário", deseja acessar seus ICommands pelos respectivos IDs.Eu tive um problema semelhante com uma ferramenta personalizada. Eu tenho um formulário personalizado que é aberto por um botão em uma barra de ferramentas AddIn no ArcGis 10.x. Neste formulário, há um botão que deve recuperar as coordenadas de um clique no mapa, incluindo os encaixes. Eu poderia iniciar a ferramenta e manipular o clique no mapa, mas não consegui recuperar o valor no meu formulário, porque a conversão para a ferramenta personalizada sempre falhava. A solução foi usar o AddIn do ESRI.ArcGIS.Desktop.AddIns. Com isso, foi fácil obter acesso a todas as propriedades e métodos da minha ferramenta personalizada. A documentação das ESRIs está aqui: http://resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/index.html#/Add_in_coding_patterns/0001000000zz000000/
Aqui está o snippet de código do OnClick-Event do botão no formulário personalizado:
fonte