ArcObjects (ArcGIS for Desktop et C #): comment effectuer un cast entre linterface utilisateur COM dArcMap et mes objets .Net UserControl personnalisés?

Je crée un utilitaire à exécuter dans ArcGIS for Desktop à laide dArcObjects (9.3.1 SDK) et C # .Net. Mon prototype implique une barre doutils avec deux des listes déroulantes et un outil. La première liste déroulante sélectionne une couche dans la table des matières, et la seconde sélectionne un champ dans la couche sélectionnée. Loutil sera utilisé pour interagir avec la carte.

En gros, je veux sélectionner un couche, sélectionnez un champ valide, puis cliquez sur une entité dans la carte et obtenez sa valeur pour le champ choisi. Voici une image de la barre doutils, si cela vous aide:

entrez la description de limage ici

[question presque entièrement reformulée à partir dici]

Le problème que jai est de passer létat entre les parties natives de linterface utilisateur COM et mes contrôles .Net personnalisés. Par exemple, je veux attraper lévénement DropDownClosed sur la liste déroulante Layer, assembler une liste valide de colonnes par rapport à cette couche, puis appliquer la liste des noms de champ (via IFields) à la liste déroulante Champs.

Après en appliquant certains des commentaires initiaux de RagiYaserBurham et blah238, et en les fusionnant avec les détails de cette page , le gestionnaire dévénement DropDownClosed suivant passe de la zone de liste déroulante à la barre doutils ( ICommandBar), mais je ne comprends pas comment effectuer un cast depuis ICommandItem vers mon implémentation de la zone de liste déroulante Fields dans 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); } 

Alors .. maintenant que Je suis ici .. comment puis-je convertir des champsItem en FieldSelectUC?

[ La solution ]

Comme blah238 la suggéré, jai essayé de lancer ICommandItem.Command dans mon implémentation UserControl personnalisée et cela a fait laffaire.

Tout dabord, jai dû ajouter un accesseur public à mon FieldSelectUC UserControl pour renvoyer une référence à son ComboBox; cet accesseur simple ressemble à ceci:

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

Avec cette modification en place, voici « un gestionnaire dévénements DropDownClosed qui remplira la combobox Champs avec tous les champs du couche sélectionnée:

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

Ceci est toujours un banc de test sale (doù AngryToolbar). Mais la solution montre comment démarrer à partir dun UserControl étendu qui implémente ICommand et IToolControl et revenir à un composant .Net. Japprécie vraiment laide de tous ceux qui ont proposé des suggestions. Merci beaucoup. 🙂

Commentaires

  • Comment à propos de rendre la portée statique publique de votre variable layerName?
  • @ artwork21, ça sonne bien, mais je ‘ ne sais toujours pas comment accéder à linstance de lune des combobox à partir de son homologue sur la barre doutils? Vous savez ce que je veux dire? Je soupçonne que ‘ est une chose fondamentale simple que je ‘ dont je ne suis tout simplement pas conscient.
  • Cela ressemble à un diff question érente. Je ‘ ne sais pas pourquoi vous devez faire cela. Il me semble que la zone de liste déroulante Champs devrait être effacée et repeuplée en fonction de la combinaison de couches. La zone de liste déroulante Layer doit être remplie en fonction de lécouteur dévénements du document.
  • @RichWawrzonek cest exactement ça. Mais je ‘ ne sais pas comment accéder à linstance existante du combo Fields à partir du combo Layers .. Dailleurs, loutil doit lire leurs deux valeurs.

Réponse

Si je comprends bien, vous avez deux ComboBox .NET sur un UserControl qui implémente ICommand et IToolControl, et vous souhaitez obtenir une référence à lune des zones de liste déroulante de lautre. Tant quils sont dans la même portée, vous devriez simplement pouvoir y faire référence par leurs noms de variables (vérifiez votre concepteur UserControl pour les noms de vos contrôles).

Si les deux zones de liste sont séparées UserControls, puis essayez de lancer ICommandItem.Command vers votre autre UserControl.

Voir cet exemple dans laide 9.3 pour quelques exemples: Fichiers récemment utilisés – Command, MultiItem et ToolControl

Voici également un message du forum ESRI traitant de ce problème: http://forums.esri.com/Thread.asp?c=93&f=993&t=170088

Commentaires

  • Bingo. Cette ligne a fait laffaire pour récupérer de linstance de ICommandItem dans la classe UserControl que jai implémentée: FieldSelectUC fs = fieldsItem.Command as FieldSelectUC; Je peux maintenant voir tous les accessoires de ‘ dans le débogueur. Un grand merci à vous.
  • Hourra! Je ‘ utilise des compléments de manière exclusive depuis un certain temps, alors jai dû fouiller dans de vieux trucs pour me rappeler comment tout fonctionnait 🙂 Ce genre de chose est beaucoup plus facile (bien que certes moins flexible) avec des compléments dans 10 car il existe un type ComboBox spécifique et vous pouvez simplement vous référer à dautres composants de complément avec des variables et des méthodes statiques.
  • Oui, cela semblait définitivement plus facile grâce aux nouveaux compléments. En recherchant ceci, jai trouvé des compléments ceci et des compléments qui, mais ils nétaient ‘ pas disponibles pour mon implémentation. Lexemple GraphicsLayerToolControl dans laide .Net (sur mon système, cette adresse est C:\Program Files (x86)\ArcGIS\DeveloperKit\SamplesNET\Desktop\GraphicsLayerToolControl\CSharp\GraphicsLayerToolControl2008.sln) qui ma aidé à démarrer avec les éléments UserControl et événements, mais je ne pouvais tout simplement pas ‘ t comprendre comment percer un trou dans .Net à partir du contrôle COM. Je ne peux ‘ exagérer à quel point je suis reconnaissant. Sincèrement.

Réponse

Chaque fois que je fais ce genre de chose, je stocke les noms de couche et de champ dans un statique jeu de propriétés contenu dans la barre doutils. Jutilise ensuite un gestionnaire dévénements de document pour vérifier si des couches sont ajoutées / supprimées dArcMap ou si le document est modifié. Les propriétés de la couche et du champ sont mises à jour chaque fois quelles sont modifiées dans la liste déroulante par lutilisateur. Si la couche est supprimée dArcMap ou si le document est fermé, elles sont réinitialisées à zéro. Ensuite, vous pouvez simplement vérifier les valeurs nulles avant lexécution de votre programme.

Obtenez une référence à la zone de liste déroulante via linterface ICommandItem:

ICommandItem toolbar = _iApp.Document.CommandBars.Find (« ArcProject.UI.AngryToolbar », false, false);
ICommandItem fieldsItem = (barre doutils sous forme de ICommandBar) .Find (« ArcProject.UI.FieldSelectUC », false); IComboBox cbo = (IComboBox) fieldsItem; // Besoin dune référence à ESRI.ArcGIS.SystemUI;

Commentaires

  • +1 vous le faites paraître si simple. 🙂 Mais le problème que jai est daccéder aux propriétés dun contrôle déjà instancié du point de vue de tout autre contrôle. Jaime votre idée de mettre leurs propriétés partagées sur la barre doutils, pourriez-vous mettre à jour votre réponse pour montrer comment je peux réellement lire les propriétés de la barre doutils contenant du point de vue de lune des listes déroulantes? ‘ Parce que ‘ est essentiellement ce que je ‘ m après. Je sais déjà comment utiliser les événements de document pour écouter les modifications apportées à la table des matières, donc je nai ‘ pas besoin daide pour cet aspect. Merci pour votre réponse.
  • @elrobis Vous pouvez également mettre létat partagé dans lICommand lui-même (car il ny aura toujours quune seule instance) et ensuite demander aux contrôles de gérer la commande via help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/…
  • Ragi est droit. Puisque vous utilisez la barre doutils COM, vous pouvez simplement passer luid de votre combobox à la méthode ICommandBar.Find pour obtenir une référence. Son lien explique tout.
  • Jaime lidée de Ragi ‘ aussi. Il y a cependant quelque chose de fondamental qui me manque. Par exemple, cette ligne renvoie une barre doutils nulle (où this est un UserControl avec libellé et combobox): ICommandBar toolbar = this.Parent as ICommandBar; Cest ‘ cette sorte de traversée dobjet de linterface utilisateur fondamentale qui me tue. Je ne sais ‘ pas comment revenir à la barre doutils pour implémenter lune de vos suggestions. (Et en fait, jaime un peu mieux lidée de ces variables sur la barre doutils. Je ‘ le ferai probablement en ajoutant un getter public à la barre doutils qui applique Ragi ). Merci pour votre aide continue.
  • Je ne ‘ je pense que this.Parent est valide pour les interfaces COM – cest-à-dire un concept .NET / Windows Forms. Vous ne ‘ ne voulez pas  » traverser linterface utilisateur « , vous voulez accéder à votre ICommandes par leur ID.

Réponse

Jai eu un problème similaire avec un outil personnalisé. Jai un formulaire personnalisé qui est ouvert par un bouton sur une barre doutils AddIn dans ArcGis 10.x. Sur ce formulaire, il y a un bouton qui devrait récupérer les coordonnées dun clic dans la carte, accrochage inclus. Je pouvais démarrer loutil et gérer le clic dans la carte, mais je ne pouvais pas récupérer la valeur dans mon formulaire, car la conversion vers loutil personnalisé échouait toujours. La solution était dutiliser AddIn de ESRI.ArcGIS.Desktop.AddIns. Avec cela, il était facile daccéder à toutes les propriétés et méthodes de mon outil personnalisé. La documentation ESRI se trouve ici: http://resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/index.html#/Add_in_coding_patterns/0001000000zz000000/

Voici lextrait de code dOnClick- Événement du bouton sur le formulaire personnalisé:

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

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *