ArcObjects (ArcGIS pentru desktop și C #): Cum să distribuiți între UI ArcMap COM și obiectele mele personalizate .Net UserControl?

Creez un utilitar pentru a rula în ArcGIS pentru desktop folosind ArcObjects (9.3.1 SDK) și C # .Net. Prototipul meu implică o bară de instrumente cu două combinate și un instrument. Primul combo selectează un strat din TOC, iar al doilea selectează un câmp din stratul selectat. Instrumentul va fi folosit pentru a interacționa cu harta.

Practic vreau să selectez un strat, selectați un câmp valid, apoi faceți clic pe o caracteristică din hartă și obțineți valoarea acestuia pentru câmpul ales. Iată o imagine a barei de instrumente, dacă ajută:

introduceți descrierea imaginii aici

[întrebare reformulată aproape în întregime de aici în jos]

Problema pe care o am este trecerea stării între piesele COM UI native și comenzile mele .Net personalizate. De exemplu, vreau să prind evenimentul DropDownClosed în caseta combinată Layer, să asamblu o listă validă de coloane în raport cu acel strat, apoi să aplic lista de nume de câmpuri (prin IFields) în caseta combinată Câmpuri.

După aplicând câteva comentarii inițiale de RagiYaserBurham și blah238 și combinându-le cu detalii din această pagină , următorul gestionar de evenimente DropDownClosed merge din caseta de comenzi înapoi în bara de instrumente ( ICommandBar), dar nu înțeleg cum să arunc de la ICommandItem înapoi la implementarea câmpului combinat Fields într-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); } 

Deci .. acum că Sunt aici .. cum pot arunca fieldItem în FieldSelectUC?

[ Soluția ]

După cum sugerează blah238, am încercat să trimit ICommandItem.Command la implementarea mea personalizată UserControl și asta a reușit.

Mai întâi, a trebuit să adaug un accesor public la FieldSelectUC UserControl pentru a returna o referință la ComboBox; acel accesor simplu arată așa:

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

Cu această modificare în loc, aici este un handler de evenimente DropDownClosed care va completa caseta de dialog Fields cu toate câmpurile din strat selectat:

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

Acesta este încă un pat de testare murdar (de aici AngryToolbar). Dar soluția arată cum să porniți de la un UserControl extins care implementează ICommand și IToolControl și reveniți la o componentă .Net. Apreciez foarte mult asistența tuturor celor care au oferit sugestii. Mulțumesc. 🙂

Comentarii

  • Cum despre cum să faceți ca layerName să fie public variabil domeniu static?
  • @ artwork21, sună bine, dar ‘ încă nu știu cum să accesez instanța oricărei combobox-uri din omologul său din bara de instrumente? Știți ce vreau să spun? Bănuiesc că ‘ este un lucru fundamental simplu pe care ‘ nu-l cunosc.
  • Sună ca o diferență întrebare erent. Nu ‘ nu știu de ce trebuie să faceți asta. Mi se pare că combobox-ul Fields ar trebui să fie șters și repopulat pe baza combo-ului Layer. Comboboxul Layer ar trebui să fie completat pe baza ascultătorului de evenimente ale documentului.
  • @RichWawrzonek, care este exact corect. Dar nu ‘ nu știu cum să ajung la instanța existentă a combo-ului Câmpuri din combo-ul Straturi. De altfel, instrumentul trebuie să le citească ambele valori.

Răspuns

După cum înțeleg, aveți două .NET ComboBox-uri pe un UserControl care implementează ICommand și IToolControl și doriți să obțineți o referință la una dintre casetele combinate de la cealaltă. Atâta timp cât acestea se află în același domeniu, ar trebui să le puteți face referire la numele variabilelor lor (verificați proiectantul UserControl pentru numele comenzilor dvs.).

Dacă cele două casete combinate sunt separate UserControls, apoi încercați să trimiteți ICommandItem.Command la celălalt UserControl.

Consultați acest exemplu în ajutorul 9.3 pentru câteva exemple: Fișiere utilizate recent – Command, MultiItem și ToolControl

De asemenea, aici este o postare pe forum ESRI care discută această problemă: http://forums.esri.com/Thread.asp?c=93&f=993&t=170088

Comentarii

  • Bingo. Această linie a făcut trucul pentru a obține din instanța ICommandItem înapoi în UserControl clasa I implementată: FieldSelectUC fs = fieldsItem.Command as FieldSelectUC; Acum pot vedea toate elementele sale ‘ în depanator. Vă mulțumim enorm.
  • Ura! ‘ folosesc add-in-uri exclusiv de ceva vreme, așa că a trebuit să cercetez câteva lucruri vechi pentru a-mi aminti cum a funcționat totul 🙂 Acest gen de lucruri este mult mai ușor (deși este adevărat mai puțin flexibil) cu programe de completare în 10 deoarece există un tip ComboBox specific și puteți face referire doar la alte componente de completare cu variabile statice și metode.
  • Da, cu siguranță părea mai ușor prin noile programe de completare. Cercetând acest lucru, am găsit programe de completare și programe de completare care, însă, nu erau ‘ t disponibile pentru implementarea mea. Exemplul GraphicsLayerToolControl din ajutorul .Net (în sistemul meu acea adresă este C:\Program Files (x86)\ArcGIS\DeveloperKit\SamplesNET\Desktop\GraphicsLayerToolControl\CSharp\GraphicsLayerToolControl2008.sln) care m-a ajutat să încep cu UserControl și evenimente, dar nu am putut ‘ nu vă dați seama cum să faceți o gaură prin .Net din controlul COM. Nu pot ‘ să exagerez cât de recunoscător sunt. Cu stimă.

Răspuns

Ori de câte ori fac acest lucru, stochez numele stratului și al câmpului într-un static set de proprietăți conținut în bara de instrumente. Apoi folosesc un document de gestionare a evenimentelor pentru a verifica dacă straturile sunt adăugate / eliminate din ArcMap sau dacă documentul este modificat. Proprietățile stratului și ale câmpului sunt actualizate ori de câte ori sunt modificate în meniul derulant de către utilizator. Dacă stratul este eliminat din ArcMap sau documentul este închis, acestea sunt resetate la nul. Apoi, puteți verifica doar valorile nule înainte de a rula programul.

Obțineți o referință la combobox prin interfața ICommandItem:

ICommandItem toolbar = _iApp.Document.CommandBars.Find („ArcProject.UI.AngryToolbar”, false, false);
ICommandItem fieldsItem = (bara de instrumente ca ICommandBar) .Găsiți („ArcProject.UI.FieldSelectUC”, false); IComboBox cbo = (IComboBox) fieldsItem; // Are nevoie de o referință la ESRI.ArcGIS.SystemUI;

Comentarii

  • +1 faceți ca acesta să sune atât de ușor. 🙂 Dar problema pe care o am este accesarea proprietăților unui control deja instanțiat din punctul de vedere al oricărui alt control. Îmi place ideea ta de a pune proprietățile lor partajate pe bara de instrumente, ai putea să îți actualizezi răspunsul pentru a arăta cum pot citi efectiv proprietățile barei de instrumente care conține din punctul de vedere al uneia din casetele combinate? ‘ Pentru că ‘ este practic ceea ce am ‘ m după. Știu deja cum să folosesc evenimentele documentelor pentru a asculta modificările TOC, așa că nu am nevoie de ‘ de ajutor cu acest aspect. Vă mulțumim pentru răspuns.
  • @elrobis Puteți, de asemenea, să puneți starea partajată în ICommand în sine (deoarece va exista întotdeauna doar o singură instanță) și apoi să le cereți comenzilor să obțină un control asupra comenzii prin help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/…
  • Ragi este dreapta. Deoarece utilizați bara de instrumente COM, puteți trece uidul combobox-ului dvs. la metoda ICommandBar.Find pentru a obține o referință. Link-ul său explică totul.
  • Îmi place și ideea lui Ragi ‘. Totuși, îmi lipsește ceva fundamental. De exemplu, această linie returnează o bară de instrumente nulă (unde this este un UserControl cu etichetă și casetă combinată): ICommandBar toolbar = this.Parent as ICommandBar; Este ‘ este acest tip de traversare fundamentală a obiectelor UI care mă ucide. Nu ‘ nu știu cum să revin la bara de instrumente pentru a implementa oricare dintre sugestiile dvs. (Și, de fapt, îmi place ideea acestor varuri pe bara de instrumente un pic mai bine. ‘ probabil o fac adăugând un getter public la bara de instrumente care aplică Ragi ‘ s idee). Vă mulțumim pentru ajutorul dvs. continuu.
  • Nu ‘ cred că this.Parent este valabil pentru interfețele COM – adică un concept .NET / Windows Forms. Nu ‘ nu doriți să ” traversați interfața de utilizare „, doriți să accesați Comenzi IC după ID-urile lor.

Răspuns

Am avut o problemă similară cu un instrument personalizat. Am un formular personalizat care se deschide printr-un buton pe o bara de instrumente AddIn în ArcGis 10.x. În acest formular există un buton care ar trebui să recupereze coordonatele unui clic pe hartă, incluzând snap-uri. Aș putea porni instrumentul și gestiona clicul pe hartă, dar nu am putut recupera valoarea înapoi la formularul meu, deoarece distribuția către instrumentul personalizat a eșuat întotdeauna. Soluția a fost să utilizați AddIn din ESRI.ArcGIS.Desktop.AddIns. Cu aceasta a fost ușor să obțin acces la fiecare proprietate și metodă a instrumentului meu personalizat. Documentația ESRI se află aici: http://resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/index.html#/Add_in_coding_patterns/0001000000zz000000/

Iată fragmentul de cod din OnClick- Evenimentul butonului din formularul personalizat:

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

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *