ArcObjects (ArcGIS untuk Desktop dan C #): Bagaimana cara melemparkan antara ArcMap COM UI dan objek UserControl .Net saya yang khusus?

8

Saya membuat utilitas untuk berjalan di ArcGIS untuk Desktop menggunakan ArcObjects (9.3.1 SDK) dan C # .Net. Prototipe saya melibatkan bilah alat dengan dua kotak kombo dan alat. Combo pertama memilih layer di TOC, dan yang kedua memilih field dari layer yang dipilih. Alat ini akan digunakan untuk berinteraksi dengan peta.

Pada dasarnya saya ingin memilih layer, pilih bidang yang valid, lalu klik fitur di peta dan dapatkan nilainya untuk bidang yang dipilih. Ini gambar toolbar, jika itu membantu:

masukkan deskripsi gambar di sini

[Pertanyaan hampir seluruhnya ditulis ulang dari sini ke bawah]

Masalah yang saya alami adalah melewati keadaan antara bagian asli COM UI dan kontrol .Net kustom saya. Misalnya, saya ingin menangkap acara DropDownClosed pada kotak kombo Layer, menyusun daftar kolom yang valid relatif terhadap lapisan itu, kemudian menerapkan daftar nama bidang (melalui IFields) ke kotak kombo Fields.

Setelah menerapkan beberapa komentar awal oleh RagiYaserBurham dan blah238, dan menggabungkannya dengan detail dari halaman ini , event handler DropDownClosed berikut ini pergi dari kotak kombo kembali ke bilah alat (ICommandBar), tapi saya tidak mengerti bagaimana cara melemparkan dari ICommandItem kembali untuk implementasi saya dari kotak kombo Fields di 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);

}

Jadi .. sekarang saya di sini .. bagaimana cara saya membuang fieldsItem ke FieldSelectUC?

[ Solusinya ]

Seperti yang disarankan blah238, saya mencoba melakukan casting ICommandItem.Command untuk implementasi UserControl kustom saya dan itu berhasil.

Pertama, saya harus menambahkan accessor publik ke FieldSelectUCUserControl saya untuk mengembalikan referensi ke ComboBox-nya; bahwa pengakses sederhana terlihat seperti ini:

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

Dengan modifikasi itu di tempatnya, inilah event handler DropDownClosed yang akan mengisi kotak kombo Fields dengan semua bidang lapisan yang dipilih:

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

Ini masih testbed kotor (karenanya AngryToolbar). Tetapi solusinya menunjukkan bagaimana memulai dari UserControl yang diperluas yang mengimplementasikan ICommand dan IToolControl dan menelusuri kembali ke komponen .Net. Saya sangat menghargai bantuan semua orang yang menawarkan saran. Terima kasih banyak. :)

elrobis
sumber
Bagaimana kalau membuat variabel static layer layerName publik Anda?
artwork21
@ artwork21, kedengarannya bagus, tapi saya masih tidak yakin bagaimana mengakses contoh combobox dari mitra di bilah alat? Tau apa yang saya maksud? Saya menduga itu adalah hal mendasar yang sederhana yang tidak saya sadari.
elrobis
Ini terdengar seperti pertanyaan yang berbeda. Saya tidak jelas mengapa Anda perlu melakukan itu. Menurut saya kotak kombo Fields harus dibersihkan dan dihuni kembali berdasarkan pada kombo Layer. Kotak kombo Layer harus diisi berdasarkan pendengar acara dokumen.
Rich Wawrzonek
@ RichWawrzonek itu memang benar. Tapi saya tidak yakin bagaimana untuk sampai ke contoh yang ada dari kombo Fields dari kombo Layers .. Untuk itu, alat perlu membaca kedua nilai mereka.
elrobis

Jawaban:

4

Seperti yang saya mengerti, Anda memiliki dua .NET ComboBoxes pada UserControl yang mengimplementasikan ICommand dan IToolControl, dan Anda ingin mendapatkan referensi ke salah satu kotak kombo dari yang lain. Selama mereka berada dalam ruang lingkup yang sama, Anda hanya bisa merujuk mereka dengan nama variabel mereka (periksa desainer UserControl Anda untuk nama-nama kontrol Anda).

Jika dua kotak kombo berada di UserControls yang terpisah, maka coba casting ICommandItem.Commandke UserControl Anda yang lain.

Lihat contoh ini di 9.3 bantuan untuk beberapa contoh: File yang terakhir digunakan - Command, MultiItem, dan ToolControl

Juga di sini adalah posting forum ESRI yang membahas masalah ini: http://forums.esri.com/Thread.asp?c=93&f=993&t=170088

blah238
sumber
Bingo. Baris ini melakukan trik untuk mendapatkan dari instance ICommandItemkembali ke UserControlkelas yang saya terapkan: FieldSelectUC fs = fieldsItem.Command as FieldSelectUC;Saya sekarang dapat melihat semua alat peraga di debugger. Terima kasih luar biasa untuk Anda.
elrobis
Hore! Saya telah menggunakan add-in secara eksklusif untuk sementara waktu sehingga saya harus menggali beberapa hal lama untuk mengingat bagaimana semuanya bekerja :) Hal semacam ini jauh lebih mudah (meskipun diakui kurang fleksibel) dengan add-in di 10 karena ada adalah tipe ComboBox tertentu dan Anda bisa merujuk ke komponen tambahan lainnya dengan variabel dan metode statis.
blah238
1
Yup, itu jelas tampak lebih mudah melalui add-in baru. Dalam meneliti ini saya menemukan tambahan ini dan tambahan itu tetapi mereka tidak tersedia untuk implementasi saya. Contoh GraphicsLayerToolControl dalam bantuan .Net (pada sistem saya yang alamatnya C:\Program Files (x86)\ArcGIS\DeveloperKit\SamplesNET\Desktop\GraphicsLayerToolControl\CSharp\GraphicsLayerToolControl2008.sln) yang membantu saya melanjutkan dengan UserControl dan hal-hal acara, tapi saya tidak tahu bagaimana cara membuat lubang melalui .Net dari kontrol COM. Saya tidak bisa melebih-lebihkan betapa bersyukurnya saya. Hormat kami.
elrobis
2

Setiap kali saya melakukan hal semacam ini, saya menyimpan nama layer dan field dalam properti statis yang terdapat di toolbar. Kemudian saya menggunakan pengendali acara dokumen untuk memeriksa apakah lapisan ditambahkan / dihapus dari ArcMap atau jika dokumen diubah. Properti layer dan field diperbarui setiap kali mereka diubah dalam drop-down oleh pengguna. Jika lapisan dihapus dari ArcMap atau dokumen ditutup, mereka diatur ulang ke nol. Kemudian Anda bisa memeriksa nilai nol sebelum program Anda berjalan.

Dapatkan referensi ke kotak kombo melalui antarmuka ICommandItem:

ICommandItem toolbar = _iApp.Document.CommandBars.Find ("ArcProject.UI.AngryToolbar", false, false);
ICommandItem fieldsItem = (toolbar sebagai ICommandBar) .Cari ("ArcProject.UI.FieldSelectUC", false); IComboBox cbo = (IComboBox) fieldsItem; // Membutuhkan referensi ke ESRI.ArcGIS.SystemUI;

Wawrzonek yang kaya
sumber
+1 Anda membuatnya terdengar sangat mudah. :) Tapi masalah yang saya miliki adalah mengakses properti dari kontrol yang sudah instantiated dari sudut pandang kontrol lain. Saya menyukai gagasan Anda untuk meletakkan properti mereka di bilah alat, dapatkah Anda memperbarui jawaban Anda untuk menunjukkan bagaimana saya dapat benar-benar membaca properti bilah alat yang berisi dari sudut pandang salah satu kotak kombo? 'Karena pada dasarnya itulah yang saya kejar. Saya sudah tahu cara menggunakan acara dokumen untuk mendengarkan perubahan pada TOC, jadi saya tidak perlu bantuan dengan aspek itu. Terimakasih atas tanggapan Anda.
elrobis
@elrobis Anda juga dapat meletakkan status bersama di ICommand itu sendiri (karena akan selalu ada hanya satu contoh) dan kemudian memiliki kontrol mendapatkan pegangan untuk perintah melalui help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp / ...
Ragi Yaser Burhum
Ragi benar. Karena Anda menggunakan COM bilah alat, Anda hanya dapat meneruskan UOB combobox Anda ke metode ICommandBar.Find untuk mendapatkan referensi. Tautannya menjelaskan semuanya.
Rich Wawrzonek
Saya suka ide Ragi juga. Ada sesuatu yang mendasar yang saya lewatkan. Misalnya, baris ini mengembalikan toolbar nol (di mana thisadalah UserControldengan label dan combobox): ICommandBar toolbar = this.Parent as ICommandBar;Ini semacam ini UI mendasar objek traversal yang membunuh saya. Saya tidak tahu cara kembali ke bilah alat untuk menerapkan salah satu saran Anda. (Dan sebenarnya saya suka ide vars ini pada toolbar sedikit lebih baik. Saya mungkin akan melakukannya dengan menambahkan getter publik ke toolbar yang menerapkan ide Ragi). Terima kasih atas bantuan Anda yang berkelanjutan.
elrobis
2
Saya tidak berpikir this.Parentini valid untuk antarmuka COM - itu adalah konsep .NET / Windows Forms. Anda tidak ingin "melintasi UI", Anda ingin mengakses ICommands dengan ID mereka.
blah238
1

Saya punya masalah serupa dengan alat kustom. Saya memiliki formulir khusus yang dibuka oleh tombol pada AddIn-Toolbar di ArcGis 10.x. Pada formulir ini ada tombol yang harus mengambil kembali koordinat klik di peta, termasuk gertakan. Saya dapat memulai alat dan menangani klik di peta, tetapi saya tidak bisa mendapatkan nilai kembali ke formulir saya, karena para pemain ke alat kustom selalu gagal. Solusinya adalah menggunakan AddIn dari ESRI.ArcGIS.Desktop.AddIns. Dengan ini, mudah untuk mendapatkan akses ke setiap properti dan metode alat kustom saya. Dokumentasi ESRI berada di sini: http://resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/index.html#/Add_in_coding_patterns/0001000000zz000000/

Berikut ini cuplikan-kode dari Acara -Klik tombol pada formulir kustom:

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