Update ComboBox during/after SendStringToExecute

Update ComboBox during/after SendStringToExecute

Anonymous
Not applicable
884 Views
3 Replies
Message 1 of 4

Update ComboBox during/after SendStringToExecute

Anonymous
Not applicable

Is it possible to update a combobox.selecteditem during a sendstringtoexecute command?

 

the code below sets the drawings current layer to a selected entities as desired but then i want to update a combobox to show the current layer.  The combobox has the current layer in it as a string.  during debigging the getsystemvariable() function returns the correct string however it says the combobox.seleceteditem = null.  Im guessing this has something to do with synchronicity but for the life of me cant figure out how to fix it.

 

        [acadRt.CommandMethod("Select_Line_Number")]
        public void SelectLineNumber()
        {
            acadApp.MainWindow.Focus();

            // create locally
            acadAp.Document document = acadAp.Application.DocumentManager.MdiActiveDocument;
            acadDb.Database database = document.Database;
            acadEd.Editor editor = acadApp.DocumentManager.MdiActiveDocument.Editor;

            // select an object
            var prompt = new acadEd.PromptSelectionOptions();
            prompt.SingleOnly = true;
            prompt.SinglePickInSpace = true;
            acadEd.PromptSelectionResult result;
            var objects = new acadDb.ObjectIdCollection();
            result = editor.GetSelection(prompt);
            if (result.Status == acadEd.PromptStatus.OK)
            {
                using (acadDb.Transaction transaction = database.TransactionManager.StartTransaction())
                {
                    // get the entity and layer from the object id
                    objects.Add(result.Value[0].ObjectId);
                    acadDb.Entity ent = transaction.GetObject(objects[0], acadDb.OpenMode.ForRead) as acadDb.Entity;
                    string lineNumber = ent.Layer;

                    // set the current layer
                    acadDb.LayerTable layerTable;
                    layerTable = transaction.GetObject(database.LayerTableId, acadDb.OpenMode.ForRead) as acadDb.LayerTable;
                    acadDb.LayerTableRecord layerRecord;
                    layerRecord = transaction.GetObject(layerTable[lineNumber], acadDb.OpenMode.ForRead) as acadDb.LayerTableRecord;
                    database.Clayer = layerTable[lineNumber];
                    this.Focus();
                    cbLineNumber.SelectedItem = acadApp.GetSystemVariable("clayer").ToString();
                    transaction.Commit();
                }
            }
            
        }
0 Likes
Accepted solutions (1)
885 Views
3 Replies
Replies (3)
Message 2 of 4

norman.yuan
Mentor
Mentor
Accepted solution

You did not provide enough information about how the combobox is hosted (modal or modeless UI?), nor how the UI class and CommandClass/Method is related. That could be the reason that your question is not getting responded. So, I had to guess, judge from your previous post, that the UI is a modeless one. 

 

Because of the 2 lines of code:

[acadRt.CommandMethod("Select_Line_Number")]
this.Focus();

I assume that your UI class (a custom PaltteSet?) is also the CommandClass with CommandMethod defined in it. If so (again guessing!), you may have a CommandMethod within the class (UI class) to show the UI itself. Then the question is: how do you define the CommandMethod? Is it a static, or not-static (as the CommandMethod you showed here)? And how the UI is instantiated (by your code, or the AutoCAD automatically because of the CommandMethod being static or non-static?

 

What I am trying to say is that mixing CommandClass/Method with UI class could be problematic, to say the least, and could be the cause of your issue (speculation without seeing more code/knowing more details).

 

With above said, I'd let the UI subscribe an even from AutoCAD, say the SystemVaralbleChanged event (i.e. when "CLAYER" changes), and update the UI accordingly, if the Model UI with said comboBox, which is meant to always showing current layer, is visible, regardless the current layer is set by your command, or by other action user does in AutoCAD. This way, you do not tie your UI updating code with your Acad action code (in your case, it is for user to select an entity and change the current layer to the layer of selected entity, right?).

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 3 of 4

Anonymous
Not applicable

Hi Norman,

 

Thanks for taking the time to read into my previous posts and piece together what i was looking for.  For reference, i did want to select an entity and change the current layer to the layer of selected entity and also update the combobox to the current layer.  I am also indeed using a modeless dialog box and based on your advice i have moved the 2 instances of a CommandMethod out of the UI class.

 

I shall endeavor to provide more complete detail in future posts when asking specifics about some code.

 

Thanks.

 

0 Likes
Message 4 of 4

_gile
Consultant
Consultant

Hi,

A modeless UI which displaying the layers in a combobox should update when the current drawing changes, same thing for the selected item (current layer) whatever the way it have been changed.

For this kind of task, AutoCAD API provides the DataBindings class accessible by Application.UIBindings property.

In this particular case, we could use the Application.UIBindings.Collections.Layers property which implements INotifyCollectionChanged and INotifyPropertyChanged.

 

Here's a little example with a simple Windows Forms modeless dialog contaning a ComboBox and a Button (note this kind of bindings is easier to implement with WPF).

The DialogBox class:

 

using Autodesk.AutoCAD.Windows.Data;

using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Windows.Forms;

using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace ModelessClayerDialog
{
    public partial class DialogBox : Form
    {
        DataItemCollection layers;

        public DialogBox()
        {
            InitializeComponent();
            layers = AcAp.UIBindings.Collections.Layers;
            comboBox1.DataSource = layers.Select(x => (INamedValue)x).ToArray();
            comboBox1.DisplayMember = "Name";
            comboBox1.SelectedItem = (INamedValue)layers.CurrentItem;
            layers.CollectionChanged += Layers_CollectionChanged;
            layers.PropertyChanged += Layers_PropertyChanged;
        }

        private void Layers_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            comboBox1.DataSource = layers.Select(x => (INamedValue)x).ToArray();
            comboBox1.DisplayMember = "Name";
        }

        private void Layers_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "CurrentItem")
                comboBox1.SelectedItem = (INamedValue)layers.CurrentItem;
        }

        private void comboBox1_SelectionChangeCommitted(object sender, EventArgs e)
        {
            layers.CurrentItem = (ICustomTypeDescriptor)comboBox1.SelectedItem;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            AcAp.MainWindow.Focus();
            var doc = AcAp.DocumentManager.MdiActiveDocument;
            if (doc != null)
                doc.SendStringToExecute("SELECTCLAYER ", false, false, true);
        }
    }
}

 

 

The Commands class:

 

using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace ModelessClayerDialog
{
    public class Commands
    {
        static DialogBox dialog;

        [CommandMethod("SHOWDIALOG")]
        public static void Test()
        {
            if (dialog == null || dialog.IsDisposed)
            {
                dialog = new DialogBox();
                AcAp.ShowModelessDialog(dialog);
            }
        }

        [CommandMethod("SELECTCLAYER")]
        public static void SelectClayer()
        {
            var doc = AcAp.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            var result = ed.GetEntity("\nSelect an entity on the layer to set current: ");
            if (result.Status == PromptStatus.OK)
            {
                using (var tr = new OpenCloseTransaction())
                {
                    var entity = (Entity)tr.GetObject(result.ObjectId, OpenMode.ForRead);
                    db.Clayer = entity.LayerId;
                    tr.Commit();
                }
            }
        }
    }
}

 

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes