ArcObjects (ArcGIS for Desktop en C #): Hoe cast ik tussen de ArcMap COM UI en mijn aangepaste .Net UserControl-objecten?

Ik “ben een hulpprogramma aan het maken om in ArcGIS for Desktop uit te voeren met ArcObjects (9.3.1 SDK) en C # .Net. Mijn prototype omvat een werkbalk met twee comboboxen en een tool. De eerste combo selecteert een laag in de inhoudsopgave en de tweede selecteert een veld uit de geselecteerde laag. De tool zal worden gebruikt om te communiceren met de kaart.

In principe wil ik een laag, selecteer een geldig veld en klik vervolgens op een object in de kaart en verkrijg de waarde voor het gekozen veld. Hier is een afbeelding van de werkbalk, als het helpt:

voer de beschrijving van de afbeelding hier in

[vraag bijna volledig opnieuw geformuleerd vanaf hier naar beneden]

Het probleem dat ik ondervind, is het doorgeven van de status tussen de native COM UI-onderdelen en mijn aangepaste .Net-besturingselementen. Ik wil bijvoorbeeld de DropDownClosed-gebeurtenis opvangen in de Layer-combobox, een geldige lijst met kolommen samenstellen ten opzichte van die laag en vervolgens de lijst met veldnamen (via IFields) toepassen op de Fields-combobox.

Daarna door de eerste opmerkingen van RagiYaserBurham en blah238 toe te passen en ze samen te voegen met details van deze pagina , gaat de volgende DropDownClosed-gebeurtenishandler van de combobox terug naar de werkbalk ( ICommandBar), maar ik begrijp niet hoe ik vanuit ICommandItem terug moet casten naar mijn implementatie van de Fields combobox in een 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); } 

Dus … nu dat Ik “ben hier .. hoe cast ik veldenItem naar FieldSelectUC?

[ De oplossing ]

Zoals blah238 suggereerde, heb ik geprobeerd ICommandItem.Command naar mijn aangepaste UserControl-implementatie te casten en dat deed het.

Eerst moest ik een publieke accessor toevoegen aan mijn FieldSelectUC UserControl om een verwijzing naar zijn ComboBox terug te sturen; die eenvoudige accessor ziet er als volgt uit:

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

Met die wijziging op zijn plaats, is hier een DropDownClosed-gebeurtenishandler die de velden-combobox zal vullen met alle velden van de geselecteerde laag:

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

Dit is nog steeds een smerig testbed (vandaar AngryToolbar). Maar de oplossing laat zien hoe te starten vanaf een uitgebreide UserControl die ICommand en IToolControl implementeert en ga terug naar een .Net-component. Ik waardeer de hulp van iedereen die suggesties heeft gedaan. Heel erg bedankt. 🙂

Opmerkingen

  • Hoe over het openbaar statisch maken van je layerName-variabele?
  • @ artwork21, dat klinkt goed, maar ik ‘ ben nog steeds niet zeker hoe ik toegang moet krijgen tot de instantie van beide comboboxen vanuit zijn tegenhanger op de werkbalk? Weet je wat ik bedoel? Ik vermoed dat het ‘ een eenvoudig fundamenteel ding is waar ik ‘ me gewoon niet van bewust ben.
  • Dit klinkt als een verschil echte vraag. Ik ‘ m niet duidelijk waarom je dat moet doen. Het lijkt mij dat de Fields-combobox moet worden gewist en opnieuw moet worden gevuld op basis van de Layer-combo. De Layer-combobox moet worden gevuld op basis van de documentgebeurtenislistener.
  • @RichWawrzonek dat is precies goed. Maar ik ‘ m weet niet zeker hoe ik bij de bestaande instantie van de Fields-combo kan komen vanuit de Layers-combo .. Wat dat betreft, moet de tool beide waarden lezen.

Answer

Zoals ik het begrijp, heb je twee .NET ComboBoxes op een UserControl die ICommand en IToolControl implementeert, en u wilt een verwijzing naar een van de keuzelijsten met invoervak van de andere krijgen. Zolang ze binnen hetzelfde bereik vallen, zou u er gewoon naar moeten kunnen verwijzen met hun variabelenamen (controleer uw UserControl-ontwerper voor de namen van uw bedieningselementen).

Als de twee keuzelijsten met invoervak afzonderlijk staan UserControls, en probeer dan ICommandItem.Command naar je andere UserControl te casten.

Zie dit voorbeeld in de 9.3 Help voor enkele voorbeelden: Recent gebruikte bestanden – Command, MultiItem en ToolControl

Ook hier is een ESRI-forumbericht waarin dit probleem wordt besproken: http://forums.esri.com/Thread.asp?c=93&f=993&t=170088

Reacties

  • Bingo. Deze regel deed het goed om van de instantie van ICommandItem terug te gaan naar de UserControl klasse die ik heb geïmplementeerd: FieldSelectUC fs = fieldsItem.Command as FieldSelectUC; Ik kan nu alle ‘ rekwisieten in de debugger zien. Enorm bedankt.
  • Hoera! Ik ‘ gebruik al een tijdje uitsluitend invoegtoepassingen, dus ik moest wat oude dingen doorzoeken om te onthouden hoe het allemaal werkte 🙂 Dit soort dingen is veel gemakkelijker (hoewel toegegeven minder flexibel) met invoegtoepassingen in 10 omdat er een specifiek ComboBox-type is en u alleen naar andere invoegtoepassingscomponenten kunt verwijzen met statische variabelen en methoden.
  • Ja, het leek zeker gemakkelijker door de nieuwe invoegtoepassingen. Bij het onderzoeken hiervan vond ik add-ins this en add-ins die maar ‘ t beschikbaar waren voor mijn implementatie. Het GraphicsLayerToolControl-voorbeeld in de .Net-help (op mijn systeem is dat adres C:\Program Files (x86)\ArcGIS\DeveloperKit\SamplesNET\Desktop\GraphicsLayerToolControl\CSharp\GraphicsLayerToolControl2008.sln) dat me hielp aan de slag te gaan met de UserControl en gebeurtenissen, maar ik kon gewoon niet ‘ t erachter komen hoe je een gat kunt slaan naar .Net vanaf de COM-besturing. Ik kan ‘ niet overdrijven hoe dankbaar ik ben. Met vriendelijke groet.

Antwoord

Telkens wanneer ik dit soort dingen doe, sla ik de laag- en veldnamen op in een statische eigenschappenset in de werkbalk. Vervolgens gebruik ik een documentgebeurtenishandler om te controleren of er lagen zijn toegevoegd / verwijderd uit ArcMap of dat het document is gewijzigd. De laag- en veldeigenschappen worden bijgewerkt wanneer ze door de gebruiker in de vervolgkeuzelijst worden gewijzigd. Als de laag uit ArcMap wordt verwijderd of het document wordt gesloten, worden ze gereset naar nul. Vervolgens kunt u gewoon op null-waarden controleren voordat uw programma wordt uitgevoerd.

Krijg een verwijzing naar de combobox via de ICommandItem-interface:

ICommandItem toolbar = _iApp.Document.CommandBars.Find (“ArcProject.UI.AngryToolbar”, false, false);
ICommandItem fieldsItem = (werkbalk als ICommandBar) .Find (“ArcProject.UI.FieldSelectUC”, false); IComboBox cbo = (IComboBox) veldenItem; // Heeft een verwijzing nodig naar ESRI.ArcGIS.SystemUI;

Reacties

  • +1 je laat het zo eenvoudig klinken. 🙂 Maar het probleem dat ik heb is toegang krijgen tot de eigenschappen van een reeds geïnstantieerde controle vanuit het oogpunt van een andere controle. Ik hou van uw idee om hun gedeelde eigenschappen op de werkbalk te plaatsen. Kunt u uw antwoord bijwerken om te laten zien hoe ik de eigenschappen van de bevattende werkbalk daadwerkelijk kan lezen vanuit het oogpunt van een van de comboboxen? ‘ Omdat ‘ eigenlijk is wat ik ‘ m daarna heb. Ik weet al hoe ik documentgebeurtenissen moet gebruiken om te luisteren naar wijzigingen in de inhoudsopgave, dus ik heb geen ‘ hulp nodig bij dat aspect. Bedankt voor je reactie.
  • @elrobis Je kunt de gedeelde status ook in de ICommand zelf plaatsen (aangezien er altijd maar één instantie zal zijn) en dan de besturing een handvat laten krijgen voor het commando via help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/…
  • Ragi is Rechtsaf. Aangezien u de COM-werkbalk gebruikt, kunt u de uid van uw combobox gewoon doorgeven aan de ICommandBar.Find-methode om een referentie te krijgen. Zijn link legt het allemaal uit.
  • Ik vind het idee van Ragi ‘ ook leuk. Er is echter iets fundamenteels dat ik mis. Deze regel retourneert bijvoorbeeld een null-werkbalk (waarbij this een UserControl is met label en combobox): ICommandBar toolbar = this.Parent as ICommandBar; Het ‘ is dit soort fundamentele UI-objectdoorgang die me kapot maakt. Ik weet niet ‘ hoe ik terug moet naar de werkbalk om een van uw suggesties te implementeren. (En eigenlijk vind ik het idee van deze variabelen op de werkbalk iets beter. Ik ‘ zou het waarschijnlijk doen door een openbare getter toe te voegen aan de werkbalk die Ragi ‘ s idee). Bedankt voor je voortdurende hulp.
  • Ik denk niet ‘ niet dat this.Parent geldig is voor COM-interfaces – dat wil zeggen een .NET / Windows Forms-concept. U ‘ wilt niet ” door de gebruikersinterface lopen “, u wilt toegang tot uw ICommandos op hun IDs.

Antwoord

Ik had een soortgelijk probleem met een aangepast hulpmiddel. Ik heb een aangepast formulier dat wordt geopend met een knop op een AddIn-Toolbar in ArcGis 10.x. Op dit formulier staat een knop die de coördinaten van een klik op de kaart moet ophalen, inclusief snappen. Ik kon de tool starten en de klik in de kaart afhandelen, maar ik kon de waarde niet terughalen naar mijn formulier, omdat de cast naar de custom-tool altijd mislukte. De oplossing was om AddIn te gebruiken van ESRI.ArcGIS.Desktop.AddIns. Hiermee was het gemakkelijk om toegang te krijgen tot alle eigendommen en methoden van mijn aangepaste tool. ESRI-documentatie bevindt zich hier: http://resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/index.html#/Add_in_coding_patterns/0001000000zz000000/

Hier is het codefragment van de OnClick- Gebeurtenis van de knop op het aangepaste formulier:

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

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *