.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

access entity event after transaction

15 REPLIES 15
Reply
Message 1 of 16
pichlP7KP6
831 Views, 15 Replies

access entity event after transaction

Hi all,

 

I want to programm a command with events. It should run like this:

First I make a prompt to pick a polyline. Then I put a event on this polyline, for example modified.

And when I modify the polyline the area of the polyline should be shown in a message box.

 

How can this event get triggered after the transaction has been ended?

 

Thank you.

Tags (2)
15 REPLIES 15
Message 2 of 16
_gile
in reply to: pichlP7KP6

Hi,

 

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

using System;

using AcCoreAp = Autodesk.AutoCAD.ApplicationServices.Core.Application;

namespace ObjectModifiedEventSample
{
    public class Commands
    {
        [CommandMethod("TEST")]
        public static void Test()
        {
            var doc = AcCoreAp.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            var options = new PromptEntityOptions("\nSelect Polyline: ");
            options.SetRejectMessage("\nSelected object is not a Polyline.");
            options.AddAllowedClass(typeof(Polyline), true);
            var result = ed.GetEntity(options);
            if (result.Status != PromptStatus.OK)
                return;
            using (var tr = db.TransactionManager.StartTransaction())
            {
                var pline = (Polyline)tr.GetObject(result.ObjectId, OpenMode.ForRead);
                pline.Modified += Pline_Modified;
                tr.Commit();
            }
        }

        private static void Pline_Modified(object sender, EventArgs e)
        {
            var pline = (Polyline)sender;
            AcCoreAp.ShowAlertDialog($"Area = {pline.Area}");
        }
    }
}


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 16
pichlP7KP6
in reply to: _gile

Thank you @_gile for the example, that's it.

 

When I save and close the document with the polyline and open it afterwards the event does not exist anymore. So I have to call the command again with every session. 

Is it possible to programm it that the event is saved and i do not have to call the command everytime again?

Message 4 of 16
_gile
in reply to: pichlP7KP6

You have to set some 'marker' to the watched polylines (xdata or extension dictionary xrecord) or store the polyline handles in a drawing dictionary so that you're able to retrieve these polylines to reset their event handlers.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 16
pichlP7KP6
in reply to: _gile

Do you have a little example how this should look like?

I can't imagine right now how to handle the attached xdata.

Message 6 of 16
_gile
in reply to: pichlP7KP6

Here's an example using a named dictionary to store the 'watched polylines' identifiers.

 

The WatchedPolyline class

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;

using System;
using System.Linq;

using AcCoreAp = Autodesk.AutoCAD.ApplicationServices.Core.Application;

namespace ObjectModifiedEventSample
{
    class WatchedPolyline
    {
        static string dictName = "GILE_MODIFIED_EVENT";
        static string xrecName => "WatchedPlines";

        public static void Pline_Modified(object sender, EventArgs e)
        {
            var pline = (Polyline)sender;
            AcCoreAp.ShowAlertDialog($"Area = {pline.Area}");
        }

        public static void AddPolyline(Transaction tr, Polyline pline)
        {
            var db = pline.Database;
            var NOD = (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
            DBDictionary dict;
            if (NOD.Contains(dictName))
            {
                dict = (DBDictionary)tr.GetObject(NOD.GetAt(dictName), OpenMode.ForRead);
            }
            else
            {
                tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForWrite);
                dict = new DBDictionary();
                NOD.SetAt(dictName, dict);
                tr.AddNewlyCreatedDBObject(dict, true);
            }
            Xrecord xrec;
            ResultBuffer data;
            if (dict.Contains(xrecName))
            {
                xrec = (Xrecord)tr.GetObject(dict.GetAt(xrecName), OpenMode.ForWrite);
                data = xrec.Data;
                if (!data.Cast<TypedValue>().Any(tv => tv.Value.Equals(pline.ObjectId)))
                {
                    data.Add(new TypedValue(330, pline.ObjectId));
                    pline.Modified += Pline_Modified;
                }
            }
            else
            {
                xrec = new Xrecord();
                dict.SetAt(xrecName, xrec);
                tr.AddNewlyCreatedDBObject(xrec, true);
                data = new ResultBuffer(new TypedValue(330, pline.ObjectId));
                pline.Modified += Pline_Modified;
            }
            xrec.Data = data;
        }

        public static void UpdatePolylines(Document doc)
        {
            var db = doc.Database;
            using (doc.LockDocument())
            using (var tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                var NOD = (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
                if (NOD.Contains(dictName))
                {
                    var dict = (DBDictionary)tr.GetObject(NOD.GetAt(dictName), OpenMode.ForRead);
                    if (dict.Contains(xrecName))
                    {
                        var xrec = (Xrecord)tr.GetObject(dict.GetAt(xrecName), OpenMode.ForWrite);
                        var data = new ResultBuffer();
                        foreach (TypedValue typedValue in xrec.Data)
                        {
                            var id = (ObjectId)typedValue.Value;
                            if (id.IsErased)
                                continue;
                            var pline = (Polyline)tr.GetObject(id, OpenMode.ForRead);
                            pline.Modified += Pline_Modified;
                            data.Add(typedValue);
                        }
                        xrec.Data = data;
                    }
                }
                tr.Commit();
            }
        }
    }
}

 

The Initialization class

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;

using System;

using AcCoreAp = Autodesk.AutoCAD.ApplicationServices.Core.Application;

namespace ObjectModifiedEventSample
{
    public class Initialization : IExtensionApplication
    {
        public void Initialize()
        {
            AcCoreAp.Idle += OnIdle;
        }

        private void OnIdle(object sender, EventArgs e)
        {
            var docs = AcCoreAp.DocumentManager;
            var acDoc = docs.MdiActiveDocument;
            if (acDoc != null)
            {
                AcCoreAp.Idle -= OnIdle;
                foreach (Document doc in docs)
                {
                    WatchedPolyline.UpdatePolylines(doc);
                }
                docs.DocumentCreated += Docs_DocumentCreated;
            }
        }

        public void Terminate()
        { }

        private void Docs_DocumentCreated(object sender, DocumentCollectionEventArgs e) =>
            WatchedPolyline.UpdatePolylines(e.Document);
    }
}

 

The Commands class

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

using AcCoreAp = Autodesk.AutoCAD.ApplicationServices.Core.Application;

namespace ObjectModifiedEventSample
{
    public class Commands
    {
        [CommandMethod("TEST")]
        public static void Test()
        {
            var doc = AcCoreAp.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            var options = new PromptEntityOptions("\nSelect Polyline: ");
            options.SetRejectMessage("\nSelected object is not a Polyline.");
            options.AddAllowedClass(typeof(Polyline), true);
            var result = ed.GetEntity(options);
            if (result.Status != PromptStatus.OK)
                return;
            using (var tr = db.TransactionManager.StartTransaction())
            {
                var pline = (Polyline)tr.GetObject(result.ObjectId, OpenMode.ForRead);
                WatchedPolyline.AddPolyline(tr, pline);
                tr.Commit();
            }
        }
    }
}

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 7 of 16
pichlP7KP6
in reply to: _gile

Thank you @_gile 

Since I have this example in my .dll my BricsCAD does not really run when I load the .dll file. Then it is very slow that you can't work with it.

I think it is because of the initialization class. When I comment this out it runs normal.

Do you know how I can solve this?

Message 8 of 16
_gile
in reply to: pichlP7KP6

This is probably dur to BricsCAD because I do not notice such problem with AutoCAD.

The initialization class is required to register the DocumentCreated and run UpdatePolylines on each already opened document when the application is loaded.

 

You can try to avoid the Idle event handling (not tested).

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;

using System;

using AcCoreAp = Autodesk.AutoCAD.ApplicationServices.Core.Application;

namespace ObjectModifiedEventSample
{
    public class Initialization : IExtensionApplication
    {
        public void Initialize()
        {
            var docs = AcCoreAp.DocumentManager;
            foreach (Document doc in docs)
            {
                WatchedPolyline.UpdatePolylines(doc);
            }
            docs.DocumentCreated += Docs_DocumentCreated;
        }

        public void Terminate()
        { }

        private void Docs_DocumentCreated(object sender, DocumentCollectionEventArgs e) =>
            WatchedPolyline.UpdatePolylines(e.Document);
    }
}

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 9 of 16
pichlP7KP6
in reply to: _gile

Thank you. With this initialization part it runs well when I use the command.

But when I safe, close and reopen the document the event is not safed...

Message 10 of 16
pichlP7KP6
in reply to: pichlP7KP6

And I tried the original initialization class in c# now and this runs. (Because first I only tried in VB.NET)

But it is the same problem that the event is not safed...

Message 11 of 16
_gile
in reply to: pichlP7KP6

When the application is loaded, the Initialize method is run and the event handlers should be add to the 'watched polylines' of every opened drawing, idem for each later created document because of the DocumentCreated handler.

 

Try putting a breakpoint at the beginning of the WatchedPolyline.UpdatePolylines() method, the execution should stop for each already opened document when the application is loaded and for each later created document.

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 12 of 16
pichlP7KP6
in reply to: _gile

Yes, when I put a breakpoint to this point it runs like in your description.

Message 13 of 16
_gile
in reply to: pichlP7KP6

And if you run a 'step by step' after the break point does it reach:

pline.Modified += Pline_Modified;

?

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 14 of 16
pichlP7KP6
in reply to: _gile

When I start debugging and open the application it skips that line because it does not get in this foreach loop.

When I draw a polyline and make the TEST command it reaches your line in the AddPolyline method.

When I save, close and reopen the drawing it reaches the line in UpdatePolylines method.

But when I step foreward and get back to the drawing the event does no more work.

Message 15 of 16
_gile
in reply to: pichlP7KP6

I'm afraid I cannot help you further.

The code I purposed works as expected with AutoCAD.

May be an issue with BricsCAD...



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 16 of 16
pichlP7KP6
in reply to: _gile

Too bad.

But thanks a lot for your efforts!

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost