ArcObjects (ArcGIS für Desktop und C #): Wie wird zwischen der ArcMap COM-Benutzeroberfläche und meinen benutzerdefinierten .Net UserControl-Objekten umgewandelt?

Ich erstelle ein Dienstprogramm, das in ArcGIS for Desktop mit ArcObjects (9.3.1 SDK) und C # .Net ausgeführt werden soll. Mein Prototyp enthält eine Symbolleiste mit zwei Kombinationsfelder und ein Werkzeug. Die erste Kombination wählt eine Ebene im Inhaltsverzeichnis und die zweite ein Feld aus der ausgewählten Ebene aus. Das Werkzeug wird zur Interaktion mit der Karte verwendet.

Grundsätzlich möchte ich eine auswählen Wählen Sie ein gültiges Feld aus, klicken Sie auf ein Feature in der Karte und rufen Sie dessen Wert für das ausgewählte Feld ab. Hier ist ein Bild der Symbolleiste, wenn dies hilfreich ist:

Geben Sie hier die Bildbeschreibung ein

[Frage von hier unten fast vollständig umformuliert]

Das Problem besteht darin, den Status zwischen den nativen COM-UI-Teilen und meinen benutzerdefinierten .NET-Steuerelementen zu übergeben. Ich möchte beispielsweise das DropDownClosed-Ereignis in der Layer-Combobox abfangen, eine gültige Liste von Spalten relativ zu dieser Layer zusammenstellen und dann die Liste der Feldnamen (über IFields) auf die Fields-Combobox anwenden.

After Wenn Sie einige der ersten Kommentare von RagiYaserBurham und blah238 anwenden und sie mit Details aus dieser Seite zusammenführen, wechselt der folgende DropDownClosed-Ereignishandler von der Combobox zurück zur Symbolleiste ( ICommandBar), aber ich verstehe nicht, wie ich von ICommandItem zu meiner Implementierung der Fields-Combobox in einem UserControl zurückkehren soll:

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

Also … jetzt das Ich bin hier. Wie wandle ich fieldsItem in FieldSelectUC um?

[ Die Lösung ]

Wie von blah238 vorgeschlagen, habe ich versucht, ICommandItem.Command in meine benutzerdefinierte UserControl-Implementierung zu übertragen, und das hat den Trick getan.

Zuerst musste ich meinem FieldSelectUC UserControl einen öffentlichen Accessor hinzufügen, um einen Verweis auf seine ComboBox zurückzugeben. Dieser einfache Accessor sieht folgendermaßen aus:

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

Mit dieser Änderung wird hier ein DropDownClosed-Ereignishandler angezeigt, der die Feld-Combobox mit allen Feldern des Felds füllt Ausgewählte Ebene:

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

Dies ist immer noch eine schmutzige Testumgebung (daher AngryToolbar). Die Lösung zeigt jedoch, wie Sie von einem erweiterten UserControl ausgehen, das ICommand und IToolControl und implementiert Drilldown zu einer .Net-Komponente. Ich schätze die Unterstützung aller, die Vorschläge gemacht haben, sehr. Vielen Dank. 🙂

Kommentare

  • Wie Über das Erstellen eines öffentlichen statischen Bereichs für Ihre LayerName-Variable?
  • @ artist21, das klingt gut, aber ich ‚ bin mir immer noch nicht sicher, wie ich auf die Instanz einer der beiden Comboboxen zugreifen soll Ich vermute, dass ‚ eine einfache grundlegende Sache ist, die mir ‚ einfach nicht bewusst ist.
  • Das klingt nach einem Unterschied andere Frage. Ich ‚ weiß nicht, warum Sie das tun müssen. Es scheint mir, dass die Feld-Combobox basierend auf der Layer-Kombination gelöscht und neu gefüllt werden sollte. Das Layer-Kombinationsfeld sollte basierend auf dem Listener für Dokumentereignisse ausgefüllt werden.
  • @RichWawrzonek, das genau richtig ist. Aber ich ‚ bin mir nicht sicher, wie ich über die Ebenen-Kombination zur vorhandenen Instanz der Feldkombination gelangen soll. In diesem Fall muss das Tool beide Werte lesen.

Antwort

Soweit ich weiß, haben Sie zwei .NET-ComboBoxen auf einem UserControl, die ICommand und IToolControl implementieren, und Sie möchten einen Verweis auf eines der Kombinationsfelder vom anderen erhalten. Solange sie sich im selben Bereich befinden, sollten Sie sie nur anhand ihrer Variablennamen referenzieren können (überprüfen Sie die Namen Ihrer Steuerelemente in Ihrem UserControl-Designer).

Wenn sich die beiden Kombinationsfelder getrennt befinden UserControls, und versuchen Sie dann, ICommandItem.Command auf Ihr anderes UserControl zu übertragen.

In diesem Beispiel in der 9.3-Hilfe finden Sie einige Beispiele: Zuletzt verwendete Dateien – Command, MultiItem und ToolControl

Auch hier ist ein ESRI-Forumsbeitrag, in dem dieses Problem behandelt wird: http://forums.esri.com/Thread.asp?c=93&f=993&t=170088

Kommentare

  • Bingo. Diese Zeile hat den Trick getan, um von der Instanz von ICommandItem zurück in die von mir implementierte UserControl -Klasse zu gelangen: FieldSelectUC fs = fieldsItem.Command as FieldSelectUC; Ich kann jetzt alle ‚ Requisiten im Debugger sehen. Vielen Dank an Sie.
  • Hurra! Ich ‚ benutze Add-Ins seit einiger Zeit exklusiv, also musste ich einige alte Sachen durchforsten, um mich daran zu erinnern, wie alles funktioniert hat 🙂 So etwas ist viel einfacher (obwohl zugegebenermaßen) weniger flexibel) mit Add-Ins in 10, da es einen bestimmten ComboBox-Typ gibt und Sie einfach auf andere Add-In-Komponenten mit statischen Variablen und Methoden verweisen können.
  • Ja, durch die neuen Add-Ins schien es definitiv einfacher zu sein. Bei der Recherche habe ich Add-Ins und Add-Ins gefunden, die jedoch für meine Implementierung nicht ‚ verfügbar waren. Das GraphicsLayerToolControl-Beispiel in der .Net-Hilfe (auf meinem System lautet die Adresse C:\Program Files (x86)\ArcGIS\DeveloperKit\SamplesNET\Desktop\GraphicsLayerToolControl\CSharp\GraphicsLayerToolControl2008.sln) hat mir geholfen, mit dem UserControl- und Ereignismaterial loszulegen, aber ich konnte einfach nicht ‚ Sie können nicht herausfinden, wie Sie ein Loch von der COM-Steuerung in .Net durchstanzen. Ich kann ‚ nicht übertreiben, wie dankbar ich bin. Mit freundlichen Grüßen.

Antwort

Immer wenn ich so etwas mache, speichere ich die Ebenen- und Feldnamen in einer statischen Eigenschaftssatz in der Symbolleiste enthalten. Dann verwende ich einen Dokumentereignishandler, um zu überprüfen, ob Ebenen zu ArcMap hinzugefügt / daraus entfernt wurden oder ob das Dokument geändert wurde. Die Ebenen- und Feldeigenschaften werden aktualisiert, wenn sie vom Benutzer in der Dropdown-Liste geändert werden. Wenn die Ebene aus ArcMap entfernt oder das Dokument geschlossen wird, werden sie auf Null zurückgesetzt. Dann können Sie einfach nach Nullwerten suchen, bevor Ihr Programm ausgeführt wird.

Rufen Sie über die ICommandItem-Schnittstelle einen Verweis auf die Combobox ab:

ICommandItem toolbar = _iApp.Document.CommandBars.Find („ArcProject.UI.AngryToolbar“, false, false);
ICommandItem fieldsItem = (Symbolleiste als ICommandBar) .Find („ArcProject.UI.FieldSelectUC“, false); IComboBox cbo = (IComboBox) fieldsItem; // Benötigt einen Verweis auf ESRI.ArcGIS.SystemUI;

Kommentare

  • +1 Sie lassen es so einfach klingen. 🙂 Aber das Problem, das ich habe, ist der Zugriff auf die Eigenschaften eines bereits instanziierten Steuerelements aus der Sicht eines anderen Steuerelements. Ich mag Ihre Idee, ihre freigegebenen Eigenschaften in die Symbolleiste aufzunehmen. Können Sie Ihre Antwort aktualisieren, um zu zeigen, wie ich die Eigenschaften der enthaltenen Symbolleiste aus der Sicht eines der Kombinationsfelder tatsächlich lesen kann? ‚ Weil ‚ im Grunde das ist, wonach ich ‚ bin. Ich weiß bereits, wie man Dokumentereignisse verwendet, um auf Änderungen am Inhaltsverzeichnis zu warten, daher brauche ich ‚ keine Hilfe bei diesem Aspekt. Vielen Dank für Ihre Antwort.
  • @elrobis Sie können den freigegebenen Status auch in den ICommand selbst einfügen (da immer nur eine Instanz vorhanden ist) und dann die Steuerelemente über help.arcgis.com/de/sdk/10.0/arcobjects_net/componenthelp/…
  • Ragi ist richtig. Da Sie die COM-Symbolleiste verwenden, können Sie die UID Ihrer Combobox einfach an die ICommandBar.Find-Methode übergeben, um eine Referenz abzurufen. Sein Link erklärt alles.
  • Ich mag auch die Idee von Ragi ‚. Es fehlt mir jedoch etwas Grundlegendes. Diese Zeile gibt beispielsweise eine Null-Symbolleiste zurück (wobei this eine UserControl mit Beschriftung und Combobox ist): ICommandBar toolbar = this.Parent as ICommandBar; Es ist ‚ diese Art von grundlegender UI-Objektdurchquerung, die mich umbringt. Ich ‚ weiß nicht, wie ich zur Symbolleiste zurückkehren kann, um einen Ihrer Vorschläge umzusetzen. (Und tatsächlich gefällt mir die Idee dieser Variablen in der Symbolleiste etwas besser. Ich ‚ würde dies wahrscheinlich tun, indem ich der Symbolleiste einen öffentlichen Getter hinzufüge, der Ragi anwendet ‚ s Idee). Vielen Dank für Ihre fortgesetzte Hilfe.
  • Ich glaube nicht, dass this.Parent für COM-Schnittstellen gültig ist – das heißt, ‚ ein .NET / Windows Forms-Konzept. Sie ‚ möchten nicht “ die Benutzeroberfläche “ durchlaufen, sondern möchten auf Ihre zugreifen Befehle nach ihren IDs.

Antwort

Ich hatte ein ähnliches Problem mit einem benutzerdefinierten Tool. Ich habe ein benutzerdefiniertes Formular, das über eine Schaltfläche in einer AddIn-Symbolleiste in ArcGis 10.x geöffnet wird. Auf diesem Formular befindet sich eine Schaltfläche, mit der die Koordinaten eines Klicks in der Karte abgerufen werden können, einschließlich des Einrastens. Ich konnte das Tool starten und den Klick in der Karte verarbeiten, aber ich konnte den Wert nicht in mein Formular zurückholen, da die Umwandlung in das benutzerdefinierte Tool immer fehlgeschlagen ist. Die Lösung bestand darin, AddIn von ESRI.ArcGIS.Desktop.AddIns zu verwenden. Auf diese Weise war es einfach, auf alle Eigenschaften und Methoden meines benutzerdefinierten Tools zuzugreifen. Die Dokumentation zu ESRIs befindet sich hier: http://resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/index.html#/Add_in_coding_patterns/0001000000zz000000/

Hier ist das Code-Snippet aus dem OnClick- Ereignis der Schaltfläche im benutzerdefinierten Formular:

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

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.