ArcObjects (ArcGIS for Desktop và C #): Làm cách nào để chuyển giữa UI UI ArcMap và các đối tượng UserControl tùy chỉnh của tôi?


8

Tôi đang tạo một tiện ích để chạy trong ArcGIS for Desktop bằng ArcObjects (9.3.1 SDK) và C # .Net. Nguyên mẫu của tôi bao gồm một thanh công cụ với hai hộp tổ hợp và một công cụ. Combo đầu tiên chọn một lớp trong TOC và thứ hai chọn một trường từ lớp đã chọn. Công cụ sẽ được sử dụng để tương tác với bản đồ.

Về cơ bản tôi muốn chọn một lớp, chọn một trường hợp lệ, sau đó nhấp vào một tính năng trong bản đồ và nhận giá trị của nó cho trường đã chọn. Đây là hình ảnh của thanh công cụ, nếu nó giúp:

nhập mô tả hình ảnh ở đây

[câu hỏi gần như hoàn toàn được diễn đạt lại từ đây xuống]

Vấn đề tôi gặp phải là chuyển trạng thái giữa các phần COM UI gốc và các điều khiển .Net tùy chỉnh của tôi. Ví dụ: tôi muốn bắt sự kiện DropDownCloses trên hộp tổ hợp Lớp, tập hợp danh sách các cột hợp lệ liên quan đến lớp đó, sau đó áp dụng danh sách tên trường (thông qua IFields) vào hộp tổ hợp Trường.

Sau khi áp dụng một số nhận xét ban đầu của RagiYaserBurham và blah238, và hợp nhất chúng với các chi tiết từ trang này , trình xử lý sự kiện DropDownCloses sau sẽ chuyển từ combobox trở lại thanh công cụ (ICommandBar), nhưng tôi không hiểu làm thế nào để quay lại từ ICommandItem để tôi triển khai hộp tổ hợp Trường trong 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);

}

Vì vậy, bây giờ tôi đang ở đây .. làm cách nào để tạo các trườngItem cho FieldSelectUC?

[ Giải pháp ]

Như blah238 đã đề xuất, tôi đã thử truyền ICommandItem.Command cho triển khai UserControl tùy chỉnh của mình và điều đó đã tạo ra mánh khóe.

Đầu tiên, tôi phải thêm một trình truy cập công khai vào FieldSelectUCUserControl của mình để trả về một tham chiếu đến ComboBox của nó; truy cập đơn giản đó trông như thế này:

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

Với sửa đổi đó, đây là trình xử lý sự kiện DropDownCloses sẽ điền vào hộp tổ hợp Trường với tất cả các trường của lớp đã chọn:

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

Đây vẫn là một thử nghiệm bẩn (do đó AngryToolbar). Nhưng giải pháp cho thấy cách bắt đầu từ UserControl mở rộng thực hiện ICommand và IToolControl và truy sâu xuống thành phần .Net. Tôi thực sự đánh giá cao sự giúp đỡ của tất cả những người đưa ra đề nghị. Cám ơn rất nhiều. :)


Làm thế nào về việc làm cho layerName biến phạm vi tĩnh công khai của bạn?
nghệ thuật21

@ tác phẩm nghệ thuật21, nghe có vẻ hay, nhưng tôi vẫn không chắc làm thế nào để truy cập vào thể hiện của combobox từ đối tác của nó trên thanh công cụ? Biết ý tôi không? Tôi nghi ngờ đó là một điều cơ bản đơn giản mà tôi không biết.
elrobis

Điều này nghe có vẻ như một câu hỏi khác nhau. Tôi không rõ tại sao bạn cần phải làm điều đó. Dường như đối với tôi, hộp tổ hợp nên được xóa và sao chép lại dựa trên kết hợp Lớp. Hộp tổ hợp lớp phải được điền dựa trên trình nghe sự kiện tài liệu.
Rich Wawrzonek

@RichWawrzonek hoàn toàn chính xác. Nhưng tôi không chắc chắn làm thế nào để có được phiên bản hiện tại của kết hợp Trường từ kết hợp Lớp .. Đối với vấn đề đó, công cụ cần phải đọc cả hai giá trị của chúng.
elrobis

Câu trả lời:


4

Theo tôi hiểu, bạn có hai ComboBox .NET trên UserControl thực hiện ICommand và IToolControl và bạn muốn có một tham chiếu đến một trong các hộp tổ hợp khác. Miễn là chúng ở trong cùng một phạm vi, bạn sẽ có thể gọi chúng theo tên biến của chúng (kiểm tra trình thiết kế UserControl của bạn để biết tên của các điều khiển của bạn).

Nếu hai hộp tổ hợp nằm trên UserControls riêng biệt, thì hãy thử truyền ICommandItem.Commandsang UserControl khác của bạn.

Xem mẫu này trong phần trợ giúp 9.3 để biết một số ví dụ: Các tệp được sử dụng gần đây - Command, MultiItem và ToolControl

Ngoài ra đây là một bài đăng trên diễn đàn ESRI thảo luận về vấn đề này: http://forums.esri.com/Thread.asp?c=93&f=993&t=170088


Chơi lô tô. Dòng này đã thực hiện thủ thuật để lấy từ ví dụ ICommandItemtrở lại UserControllớp tôi đã triển khai: FieldSelectUC fs = fieldsItem.Command as FieldSelectUC;Bây giờ tôi có thể thấy tất cả các đạo cụ của nó trong trình gỡ lỗi. Rất cảm ơn bạn.
elrobis

Hoan hô! Tôi đã sử dụng bổ trợ một cách độc quyền trong một thời gian vì vậy tôi đã phải tìm hiểu một số nội dung cũ để nhớ cách thức hoạt động của nó :) Loại điều này dễ dàng hơn nhiều (mặc dù được thừa nhận là kém linh hoạt hơn) với các bổ trợ trong 10 kể từ đó là một loại ComboBox cụ thể và bạn chỉ có thể tham khảo các thành phần bổ trợ khác với các biến và phương thức tĩnh.
blah238

1
Yup, nó chắc chắn có vẻ dễ dàng hơn thông qua các add-in mới. Trong nghiên cứu này, tôi đã tìm thấy bổ trợ này và bổ trợ đó nhưng chúng không có sẵn để tôi thực hiện. Ví dụ GraphicsLayerToolControl trong trợ giúp .Net (trên hệ thống của tôi là địa chỉ C:\Program Files (x86)\ArcGIS\DeveloperKit\SamplesNET\Desktop\GraphicsLayerToolControl\CSharp\GraphicsLayerToolControl2008.sln) đã giúp tôi bắt đầu với công cụ UserControl và các sự kiện, nhưng tôi không thể tìm ra cách đục lỗ thông qua .Net từ điều khiển COM. Tôi không thể phóng đại rằng tôi biết ơn như thế nào. Trân trọng.
elrobis

2

Bất cứ khi nào tôi làm điều này, tôi lưu trữ tên lớp và trường trong một tập thuộc tính tĩnh có trong thanh công cụ. Sau đó, tôi sử dụng một trình xử lý sự kiện tài liệu để kiểm tra xem các lớp được thêm / xóa khỏi ArcMap hay nếu tài liệu bị thay đổi. Các thuộc tính lớp và trường được cập nhật bất cứ khi nào chúng được người dùng thay đổi trong trình đơn thả xuống. Nếu lớp bị xóa khỏi ArcMap hoặc tài liệu bị đóng, chúng sẽ được đặt lại thành null. Sau đó, bạn chỉ có thể kiểm tra giá trị null trước khi chương trình của bạn chạy.

Nhận tham chiếu đến combobox thông qua giao diện ICommandItem:

Thanh công cụ ICommandItem = _iApp.Document.CommandBars.Find ("ArcProject.UI.AngryToolbar", sai, sai);
Các trường ICommandItemItem = (thanh công cụ là ICommandBar) .Tìm ("ArcProject.UI.FieldSelectUC", sai); Các trường IComboBox cbo = (IComboBox); // Cần một tham chiếu đến ESRI.ArcGIS.SystemUI;


+1 bạn làm cho âm thanh rất dễ dàng. :) Nhưng vấn đề tôi gặp phải là truy cập vào các thuộc tính của một điều khiển đã được khởi tạo từ quan điểm của bất kỳ điều khiển nào khác. Tôi thích ý tưởng của bạn về việc đặt các thuộc tính được chia sẻ của chúng trên thanh công cụ, bạn có thể cập nhật câu trả lời của mình để cho biết cách tôi thực sự có thể đọc các thuộc tính của thanh công cụ chứa theo quan điểm của một trong các hộp tổ hợp không? 'Về cơ bản đó là những gì tôi đang theo đuổi. Tôi đã biết cách sử dụng các sự kiện tài liệu để lắng nghe các thay đổi đối với TOC, vì vậy tôi không cần trợ giúp về khía cạnh đó. Cám ơn phản hồi của bạn.
elrobis

@elrobis Bạn cũng có thể đặt trạng thái chia sẻ trong chính ICommand (vì sẽ luôn chỉ có một thể hiện) và sau đó các điều khiển sẽ xử lý lệnh thông qua help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp /
Lọ

Ragi nói đúng. Vì bạn đang sử dụng thanh công cụ COM, bạn có thể chuyển uid của combobox của mình sang phương thức ICommandBar.Find để có được một tham chiếu. Liên kết của anh ấy giải thích tất cả.
Rich Wawrzonek

Tôi cũng thích ý tưởng của Ragi. Có một cái gì đó cơ bản tôi đang thiếu, mặc dù. Chẳng hạn, dòng này trả về một thanh công cụ null (trong đó có nhãn và thishộp UserControltổ hợp): ICommandBar toolbar = this.Parent as ICommandBar;Đây là loại giao diện đối tượng UI cơ bản đang giết chết tôi. Tôi không biết làm thế nào để quay lại thanh công cụ để thực hiện một trong các đề xuất của bạn. (Và thực sự tôi thích ý tưởng của những chiếc bình này trên thanh công cụ tốt hơn một chút. Có lẽ tôi sẽ thực hiện nó bằng cách thêm một getter công khai vào thanh công cụ áp dụng ý tưởng của Ragi). Cảm ơn vì sự giúp đỡ tiếp tục của bạn.
elrobis

2
Tôi không nghĩ this.Parentlà hợp lệ cho các giao diện COM - đó là khái niệm .NET / Windows Forms. Bạn không muốn "duyệt qua UI", bạn muốn truy cập ICommands của mình bằng ID của họ.
blah238

1

Tôi đã có một vấn đề tương tự với một công cụ tùy chỉnh. Tôi có một biểu mẫu tùy chỉnh được mở bằng một nút trên Thanh công cụ AddIn trong ArcGis 10.x. Trên biểu mẫu này có một nút nên truy xuất tọa độ của một lần nhấp trong bản đồ, chụp kèm theo. Tôi có thể khởi động công cụ và xử lý nhấp chuột trên bản đồ, nhưng tôi không thể lấy lại giá trị về biểu mẫu của mình, vì việc chuyển sang công cụ tùy chỉnh luôn thất bại. Giải pháp là sử dụng AddIn từ ESRI.ArcGIS.Desktop.AddIns. Với điều này, thật dễ dàng để có quyền truy cập vào mọi tài sản và phương thức của công cụ tùy chỉnh của tôi. Tài liệu ESRIs cư trú tại đây: http://resource.arcgis.com/en/help/arcobjects-net/conceptualhelp/index.html#/Add_in_coding_potypes/0001000000zz000000/

Đây là đoạn mã từ OnClick-Event của nút trên biểu mẫu tùy chỉnh:

//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;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.