Jag skapar ett verktyg som ska köras i ArcGIS för Desktop med ArcObjects (9.3.1 SDK) och C # .Net. Min prototyp innefattar ett verktygsfält med två kombinationsrutor och ett verktyg. Den första kombinationen väljer ett lager i innehållsförteckningen och det andra markerar ett fält från det valda lagret. Verktyget kommer att användas för att interagera med kartan.
I grund och botten vill jag välja en lager, välj ett giltigt fält och klicka sedan på en funktion på kartan och få värdet för det valda fältet. Här är en bild av verktygsfältet, om det hjälper:
[fråga nästan helt omformulerad härifrån]
Problemet jag har är att skicka tillstånd mellan de inbyggda COM UI-delarna och mina anpassade .Net-kontroller. Till exempel vill jag fånga DropDownClosed-händelsen i kombinationsrutan Layer, sätta ihop en giltig lista med kolumner i förhållande till det lagret och tillämpa sedan listan med fältnamn (via IFields) i fältkombinationen.
Efter tillämpa några av de första kommentarerna från RagiYaserBurham och blah238 och slå samman dem med detaljer från den här sidan , går följande DropDownClosed-händelsehanterare från kombinationsrutan till verktygsfältet ICommandBar), men jag förstår inte hur jag ska kasta från ICommandItem tillbaka till min implementering av fältkombinationen i en 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); }
Så .. nu att Jag är här .. hur kastar jag fältItem till FieldSelectUC?
[ Lösningen ]
Som blah238 föreslog, försökte jag kasta ICommandItem.Command till min anpassade UserControl-implementering och det gjorde tricket.
Först var jag tvungen att lägga till en allmän accessor till min FieldSelectUC
UserControl för att returnera en referens till dess ComboBox; den enkla accessorn ser ut så här:
// fieldSelectCBO is the name of the combobox control in the design view.. public ComboBox FieldsComboBox { get { return fieldSelectCBO; } }
Med den modifieringen på plats är det här en DropDownClosed-händelsehanterare som fyller fältkombinationen med alla fält i valt lager:
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!"); } }
Detta är fortfarande en smutsig testbädd (därmed AngryToolbar). Men lösningen visar hur man startar från en utökad UserControl som implementerar ICommand och IToolControl och borra ner till en .Net-komponent. Jag uppskattar verkligen hjälpen från alla som erbjöd förslag. Tack så mycket. 🙂
Kommentarer
- Hur om att göra din layerName-variabel offentlig statisk räckvidd?
- @ artwork21, det låter bra, men jag ’ är fortfarande inte säker på hur jag kommer åt instansen av någon av kombinationsrutorna från dess motsvarighet i verktygsfältet? Vet vad jag menar? Jag misstänker att det ’ är en enkel grundläggande sak jag ’ är bara inte medveten om.
- Detta låter som en diff erent fråga. Jag ’ är inte klar över varför du behöver göra det. Det verkar för mig att Fields-kombinationsrutan ska rensas och befolkas på nytt baserat på Layer-kombinationen. Layer-kombinationsrutan ska fyllas ut baserat på dokumenthändelselyssnaren.
- @RichWawrzonek som är exakt rätt. Men jag ’ är inte säker på hur jag ska komma till den befintliga instansen av fältkombinationen från kombinationsskiktet. För den delen måste verktyget läsa båda deras värden.
Svar
Som jag förstår det har du två .NET ComboBoxes på en UserControl som implementerar ICommand och IToolControl, och du vill få en hänvisning till en av kombinationsrutorna från den andra. Så länge de är i samma omfattning borde du bara kunna hänvisa till dem med deras variabla namn (kolla din UserControl-designer för namnen på dina kontroller).
Om de två kombinationsrutorna finns på separata UserControls, försök sedan att kasta ICommandItem.Command
till din andra UserControl.
Se det här exemplet i 9.3-hjälpen för några exempel: Nyligen använda filer – Command, MultiItem och ToolControl
Här finns också ett ESRI-foruminlägg som diskuterar detta problem: http://forums.esri.com/Thread.asp?c=93&f=993&t=170088
Kommentarer
- Bingo. Denna rad gjorde tricket för att komma från instansen av
ICommandItem
tillbaka tillUserControl
klass jag implementerade:FieldSelectUC fs = fieldsItem.Command as FieldSelectUC;
Jag kan nu se allt det ’ s rekvisita i felsökaren. Stort tack till dig. - Hurra! Jag ’ har använt tillägg exklusivt ett tag så jag var tvungen att gräva igenom några gamla saker för att komma ihåg hur det hela fungerade 🙂 Den här typen av saker är mycket lättare (dock visserligen mindre flexibel) med tillägg i 10 eftersom det finns en specifik ComboBox-typ och du kan bara hänvisa till andra tilläggskomponenter med statiska variabler och metoder.
- Japp, det verkade definitivt lättare genom de nya tilläggen. När jag undersökte detta fann jag tillägg detta och tillägg som men de var bara ’ t tillgängliga för min implementering. GraphicsLayerToolControl-exemplet i .Net-hjälpen (på mitt system är adressen
C:\Program Files (x86)\ArcGIS\DeveloperKit\SamplesNET\Desktop\GraphicsLayerToolControl\CSharp\GraphicsLayerToolControl2008.sln
) som hjälpte mig att komma igång med UserControl och händelser, men jag kunde bara inte ’ räkna inte ut hur man stänger ett hål till .Net från COM-kontrollen. Jag kan ’ inte överdriva hur tacksam jag är. Med vänliga hälsningar.
Svar
När jag gör den här typen av saker lagrar jag lager- och fältnamnen i en statisk fastighetsuppsättning som finns i verktygsfältet. Sedan använder jag en dokumenthändelsehanterare för att kontrollera om lager läggs till / tas bort från ArcMap eller om dokumentet ändras. Skikt- och fältegenskaperna uppdateras när de ändras i rullgardinsmenyn av användaren. Om skiktet tas bort från ArcMap eller dokumentet stängs återställs de till noll. Då kan du bara söka efter nollvärden innan programmet körs.
Få en referens till kombinationsrutan via ICommandItem-gränssnittet:
ICommandItem-verktygsfält = _iApp.Document.CommandBars.Find (”ArcProject.UI.AngryToolbar”, false, false);
ICommandItem fieldsItem = (verktygsfält som ICommandBar) .Find (”ArcProject.UI.FieldSelectUC”, false); IComboBox cbo = (IComboBox) fieldItem; // Behöver en hänvisning till ESRI.ArcGIS.SystemUI;
Kommentarer
- +1 du får det att låta så enkelt. 🙂 Men problemet jag har är att få tillgång till egenskaperna för en redan instanterad styrning ur någon annan kontrolls synvinkel. Jag gillar din idé att placera deras delade egenskaper i verktygsfältet. Kan du uppdatera ditt svar för att visa hur jag faktiskt kan läsa egenskaperna för det innehållande verktygsfältet från en av kombinationsrutorna? ’ Cos att ’ är i grund och botten vad jag ’ efter. Jag vet redan hur man använder dokumenthändelser för att lyssna efter ändringar i innehållsförteckningen, så jag behöver inte ’ hjälp med den aspekten. Tack för ditt svar.
- @elrobis Du kan också sätta delat tillstånd i själva IC-kommandot (eftersom det alltid bara kommer att finnas en instans) och sedan få kontrollerna att hantera kommandot genom help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/…
- Ragi är rätt. Eftersom du använder COM-verktygsfältet kan du bara skicka uid för kombinationsrutan till ICommandBar.Find-metoden för att få en referens. Hans länk förklarar allt.
- Jag gillar också Ragi ’ s idé. Det finns dock något grundläggande jag saknar. Till exempel returnerar denna rad ett nollverktygsfält (där
this
är enUserControl
med etikett och kombinationsruta):ICommandBar toolbar = this.Parent as ICommandBar;
Det ’ är den här typen av grundläggande gränssnitt för UI-objekt som dödar mig. Jag vet inte ’ hur jag kommer tillbaka till verktygsfältet för att implementera något av dina förslag. (Och faktiskt gillar jag tanken på dessa vars i verktygsfältet lite bättre. Jag ’ d gör det förmodligen genom att lägga till en offentlig getter i verktygsfältet som tillämpar Ragi ’ idé). Tack för din fortsatta hjälp. - Jag tror inte ’ t
this.Parent
är giltigt för COM-gränssnitt – det vill säga ett .NET / Windows Forms-koncept. Du vill ’ t ” korsa gränssnittet ”, du vill komma åt din IC-kommandon efter deras ID.
Svar
Jag hade ett liknande problem med ett anpassat verktyg. Jag har ett anpassat formulär som öppnas med en knapp i ett AddIn-Toolbar i ArcGis 10.x. På det här formuläret finns en knapp som ska hämta koordinaterna för ett klick på kartan, inklusive snapping. Jag kunde starta verktyget och hantera klicket på kartan, men jag kunde inte få tillbaka värdet till mitt formulär, eftersom casten till det anpassade verktyget alltid misslyckades. Lösningen var att använda AddIn från ESRI.ArcGIS.Desktop.AddIns. Med detta var det enkelt att få tillgång till varje egendom och metod för mitt anpassade verktyg. ESRIs dokumentation finns här: http://resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/index.html#/Add_in_coding_patterns/0001000000zz000000/
Här är kodavsnittet från OnClick- Händelse av knappen i det anpassade formuläret:
//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;