ArcObjects (ArcGIS for Desktop og C #): Hvordan kastes mellem ArcMap COM UI og mine brugerdefinerede .Net UserControl-objekter?

Jeg opretter et hjælpeprogram til at køre i ArcGIS til Desktop ved hjælp af ArcObjects (9.3.1 SDK) og C # .Net. Min prototype involverer en værktøjslinje med to comboboxes og et værktøj. Den første kombinationsboks vælger et lag i TOC, og det andet markerer et felt fra det valgte lag. Værktøjet bruges til at interagere med kortet.

Grundlæggende vil jeg vælge en lag, vælg et gyldigt felt, og klik derefter på en funktion på kortet, og få værdien for det valgte felt. Her er et billede af værktøjslinjen, hvis det hjælper:

indtast billedbeskrivelse her

[spørgsmål næsten helt omformuleret herfra og ned]

Det problem, jeg har, er at føre tilstand mellem de oprindelige COM UI-dele og mine brugerdefinerede .Net-kontroller. For eksempel vil jeg fange DropDownClosed-begivenheden på Layer-kombinationsboksen, samle en gyldig liste over kolonner i forhold til det lag og derefter anvende listen over feltnavne (via IFields) i kombinationsboksen Fields.

Efter anvender nogle af de indledende kommentarer fra RagiYaserBurham og blah238 og fletter dem med detaljer fra denne side , den følgende DropDownClosed-begivenhedshåndterer går fra kombinationsboksen tilbage til værktøjslinjen ICommandBar), men jeg forstår ikke, hvordan jeg kan kaste fra ICommandItem tilbage til min implementering af feltkombinationen 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, Jeg er her .. hvordan kaster jeg feltItem til FieldSelectUC?

[ Løsningen ]

Som blah238 foreslog, prøvede jeg at kaste ICommandItem.Command til min brugerdefinerede UserControl-implementering, og det gjorde tricket.

Først måtte jeg tilføje en offentlig adgang til min FieldSelectUC UserControl for at returnere en henvisning til dens ComboBox; den enkle accessor ser sådan ud:

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

Med denne ændring på plads, her “en DropDownClosed begivenhedshåndterer, der udfylder feltkombinationen med alle felterne i valgt lag:

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

Dette er stadig en beskidt testbed (deraf AngryToolbar). Men løsningen viser, hvordan man starter fra en udvidet UserControl, der implementerer ICommand og IToolControl og bore ned til en .Net-komponent. Jeg sætter stor pris på hjælp fra alle, der tilbød forslag. Mange tak. 🙂

Kommentarer

  • Hvordan om at gøre dit lagnavn variabelt offentligt statisk omfang?
  • @ artwork21, det lyder godt, men jeg ‘ er stadig ikke sikker på, hvordan jeg får adgang til forekomsten af begge kombinationsbokse fra dens modstykke på værktøjslinjen? Ved du hvad jeg mener? Jeg formoder, at det ‘ er en simpel grundlæggende ting, jeg ‘ er bare ikke opmærksom på.
  • Dette lyder som en forskel uklar spørgsmål. Jeg ‘ er ikke klar over, hvorfor du skal gøre det. Det forekommer mig, at kombinationsfeltet Fields skal ryddes og genbefolkes baseret på Layer-kombinationsboksen. Lagkombinationen skal udfyldes baseret på dokumenthændelseslytteren.
  • @RichWawrzonek det er nøjagtigt korrekt. Men jeg ‘ er ikke sikker på, hvordan man kommer til den eksisterende forekomst af feltkombinationen fra kombinationskombinationen. For den sags skyld skal værktøjet læse begge deres værdier.

Svar

Som jeg forstår det, har du to .NET ComboBoxes på en UserControl, der implementerer ICommand og IToolControl, og du ønsker at få en henvisning til et af kombinationsfelterne fra det andet. Så længe de er i samme omfang, skal du bare kunne henvise til dem ved hjælp af deres variabelnavne (tjek din UserControl-designer for navnene på dine kontrolelementer).

Hvis de to kombinationsfelter er adskilt UserControls, så prøv at caste ICommandItem.Command til din anden UserControl.

Se denne prøve i 9.3 hjælp til nogle eksempler: Nyligt anvendte filer – Command, MultiItem og ToolControl

Også her er et ESRI-forumindlæg, der diskuterer dette problem: http://forums.esri.com/Thread.asp?c=93&f=993&t=170088

Kommentarer

  • Bingo. Denne linje gjorde tricket for at komme fra forekomsten af ICommandItem tilbage til UserControl klasse jeg implementerede: FieldSelectUC fs = fieldsItem.Command as FieldSelectUC; Jeg kan nu se alt det ‘ s rekvisitter i debuggeren. Enorm tak til dig.
  • Hurra! Jeg ‘ har brugt tilføjelsesprogrammer eksklusivt i et stykke tid, så jeg var nødt til at grave igennem nogle gamle ting for at huske, hvordan det hele fungerede 🙂 Denne slags ting er meget lettere (dog ganske vist mindre fleksibel) med tilføjelsesprogrammer i 10, da der er en bestemt ComboBox-type, og du bare kan henvise til andre tilføjelseselementer med statiske variabler og metoder.
  • Ja, det syntes bestemt lettere gennem de nye tilføjelser. Når jeg undersøgte dette, fandt jeg tilføjelsesprogrammer dette og tilføjelsesprogrammer, men de var bare ‘ t tilgængelige for min implementering. GraphicsLayerToolControl-eksemplet i .Net-hjælp (på mit system er adressen C:\Program Files (x86)\ArcGIS\DeveloperKit\SamplesNET\Desktop\GraphicsLayerToolControl\CSharp\GraphicsLayerToolControl2008.sln), der hjalp mig med at komme i gang med UserControl og events-ting, men jeg kunne bare ikke ‘ ikke finde ud af, hvordan man kan slå et hul igennem til .Net fra COM-kontrollen. Jeg kan ‘ ikke overdrive, hvor taknemmelig jeg er. Med venlig hilsen.

Svar

Når jeg gør denne slags ting, gemmer jeg lag- og feltnavne i en statisk egenskabssæt indeholdt i værktøjslinjen. Derefter bruger jeg en dokumenthændelseshåndterer til at kontrollere, om lag tilføjes / fjernes fra ArcMap, eller om dokumentet ændres. Lag- og feltegenskaberne opdateres, hver gang de ændres i rullemenuen af brugeren. Hvis laget fjernes fra ArcMap, eller dokumentet lukkes, nulstilles de til null. Derefter kan du bare kontrollere nulværdier, før dit program kører.

Få en reference til kombinationsboksen gennem ICommandItem-grænsefladen:

ICommandItem-værktøjslinje = _iApp.Document.CommandBars.Find (“ArcProject.UI.AngryToolbar”, false, false);
ICommandItem fieldsItem = (værktøjslinje som ICommandBar) .Find (“ArcProject.UI.FieldSelectUC”, false); IComboBox cbo = (IComboBox) felterItem; // Har brug for en henvisning til ESRI.ArcGIS.SystemUI;

Kommentarer

  • +1 du får det til at lyde så let. 🙂 Men det problem, jeg har, er at få adgang til egenskaberne for en allerede insti-nenteret kontrol fra ethvert andet kontrolperspektiv. Jeg kan godt lide din idé om at placere deres delte egenskaber på værktøjslinjen. Kan du opdatere dit svar for at vise, hvordan jeg rent faktisk kan læse egenskaberne for den indeholdende værktøjslinje set fra en af kombinationsboksenes synspunkt? ‘ Fordi ‘ s grundlæggende hvad jeg ‘ m efter. Jeg ved allerede, hvordan man bruger dokumenthændelser til at lytte efter ændringer i indholdsfortegnelsen, så jeg behøver ikke ‘ hjælp til dette aspekt. Tak for dit svar.
  • @elrobis Du kan også placere den delte tilstand i selve IC-kommandoen (da der altid kun vil være en forekomst) og derefter få kontrolelementerne til at håndtere kommandoen gennem help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/…
  • Ragi er ret. Da du bruger COM-værktøjslinjen, kan du bare overføre uid for din kombinationsboks til ICommandBar.Find-metoden for at få en reference. Hans link forklarer det hele.
  • Jeg kan også lide Ragi ‘ s idé. Der er dog noget grundlæggende, jeg mangler. For eksempel returnerer denne linje en nul værktøjslinje (hvor this er en UserControl med etiket og kombinationsboks): ICommandBar toolbar = this.Parent as ICommandBar; Det ‘ er denne form for grundlæggende UI-objektgennemgang, der dræber mig. Jeg ved ikke ‘ hvordan man kommer tilbage til værktøjslinjen for at implementere et af dine forslag. (Og faktisk kan jeg godt lide ideen om disse vars på værktøjslinjen lidt bedre. Jeg ‘ d gør det sandsynligvis ved at tilføje en offentlig getter til værktøjslinjen, der anvender Ragi ‘ s idé). Tak for din fortsatte hjælp.
  • Jeg tror ikke ‘ t this.Parent er gyldig til COM-grænseflader – det vil sige et .NET / Windows Forms-koncept. Du vil ikke ‘ ikke ” krydse brugergrænsefladen “, du vil have adgang til din IC-kommandoer efter deres ider.

Svar

Jeg havde et lignende problem med et brugerdefineret værktøj. Jeg har en brugerdefineret form, som åbnes med en knap på en AddIn-Toolbar i ArcGis 10.x. På denne formular er der en knap, der skal hente koordinaterne for et klik på kortet, inklusive snapping. Jeg kunne starte værktøjet og håndtere klik på kortet, men jeg kunne ikke få værdien tilbage til min formular, fordi casten til det brugerdefinerede værktøj altid mislykkedes. Løsningen var at bruge AddIn fra ESRI.ArcGIS.Desktop.AddIns. Med dette var det let at få adgang til hver ejendom og metode til mit tilpassede værktøj. ESRIs-dokumentation findes her: http://resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/index.html#/Add_in_coding_patterns/0001000000zz000000/

Her er kodestykket fra OnClick- Begivenhed for knappen på den brugerdefinerede form:

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

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *