Author Topic: Deleting XData: Don't Delete the registered app(1001) TypedValue.  (Read 2366 times)

0 Members and 1 Guest are viewing this topic.

Atook

  • Swamp Rat
  • Posts: 1027
  • AKA Tim
I ran into an interesting problem, got it to work, but the answer isn't making sense in my head.

The task is to delete the xData for a registered app on a given entity. You can see I basically copy all the existing xData into a new ResultBuffer, and leave out the TypedValues from the 'offending' registered app. Well it wasn't working. I'd step through the code, and see the updated ResultBuffer written to the object, with no error thrown. I'd check the entity with dxflist, and the 'offending' xData was still there. Looking at this post, I noticed that that Virupaksha leaves the 1001 typed value in the xdata, so I tried that (line 27) and it seems to work.

Code - C#: [Select]
  1. /// <summary>
  2. /// Deletes xdata under the regsitered app specified.
  3. /// </summary>
  4. /// <param name="objID">The object identifier.</param>
  5. /// <param name="appName">name of the registered app to delete</param>
  6. public static void DeleteXData(ObjectId objID, string appName)
  7. {
  8.         if (appName.Length<1) return;
  9.         ResultBuffer updatedXdata = new ResultBuffer();
  10.         using (LockedTransaction tr = Active.Document.TransactionManager.StartLockedTransaction())
  11.         {
  12.                 // remove any xdata for the given appname
  13.                 DBObject obj = tr.GetObject(objID, OpenMode.ForWrite);
  14.                 ResultBuffer existingData = obj.XData;
  15.                 if (existingData!=null)
  16.                 {
  17.                         bool included = true;
  18.                         // Get all values NOT with our Registered App
  19.                         foreach (TypedValue tv in existingData)
  20.                         {
  21.                                 // check whether to keep it
  22.                                 if (tv.TypeCode == CODE_APPNAME)
  23.                                 {
  24.                                         if (appName.Equals(tv.Value.ToString()))
  25.                                         {
  26.                                                 // add the appname TV or the xData doesn't get set correctly and reverts back to the old xData
  27.                                                 updatedXdata.Add(tv);
  28.                                                 included = false;
  29.                                         }
  30.                                         else
  31.                                         {
  32.                                                 included = true;
  33.                                         }
  34.                                 }
  35.                                 if (included)
  36.                                 {
  37.                                         updatedXdata.Add(tv);
  38.                                 }
  39.                         }
  40.                         RegisterApps(updatedXdata);
  41.                         obj.XData = updatedXdata;
  42.                 }
  43.                 tr.Commit();
  44.         }
  45. }

After running this, the offending registered app is no longer included in the xdata. I'm confused why I had to include the registered app TV in the updated xdata, and was hoping someone here could either provide an explanation or point me something in the dev docs that explain this. Primarily for the sake of easing my mind that I (hopefully) am doing it right, and also to help others (maybe future me) down the road.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Deleting XData: Don't Delete the registered app(1001) TypedValue.
« Reply #1 on: August 09, 2016, 01:54:54 AM »
Hi,

As a same object can have xdata for several registered applications, when you want to remove the xdata for one of the registered applications, you have to specify which one.
Maybe something confusing with .NET is the use of a ResultBuffer in which the registered application is a TypedValue at same level as data.
With AutoLISP (DXF) the xdata are contained in a -3 group list of sublists which is more "self decribing" the xdata architecture:
(-3 ("RegApp1" (1000 . "foo") (1070 . 42)) ("RegApp2" (1000 . "bar)))
« Last Edit: August 09, 2016, 02:00:14 AM by gile »
Speaking English as a French Frog

Atook

  • Swamp Rat
  • Posts: 1027
  • AKA Tim
Re: Deleting XData: Don't Delete the registered app(1001) TypedValue.
« Reply #2 on: August 09, 2016, 02:07:50 AM »
Thanks Gile, my code does works with multiple registered applications in the xData for a given entity. updatedXdata contains the xdata for all apps that are to remain on the object; and gets written back to the object at the end of the routine.

I'm just trying to understand why I add  the typed value for the deleted app back into the updated ResultBuffer on line 27.

It's late and I've been beating my head against this for a while. Perhaps I'll be able to describe my question better in the morning. Thanks again for taking a look.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Deleting XData: Don't Delete the registered app(1001) TypedValue.
« Reply #3 on: August 09, 2016, 08:23:44 AM »
Try this way

Code - C#: [Select]
  1.         public static void DeleteXData(ObjectId objID, string appName)
  2.         {
  3.             if (appName.Length < 1) return;
  4.             ResultBuffer updatedXdata = new ResultBuffer();
  5.             Document doc = Application.DocumentManager.MdiActiveDocument;
  6.             using (doc.LockDocument())
  7.             using (var tr = doc.TransactionManager.StartTransaction())
  8.             {
  9.                 // remove any xdata for the given appname (if any)
  10.                 DBObject obj = tr.GetObject(objID, OpenMode.ForWrite);
  11.                 obj.XData = new ResultBuffer(new TypedValue(CODE_APPNAME, appName));
  12.                 RegisterApps(obj.XData);
  13.                 tr.Commit();
  14.             }
  15.         }
Speaking English as a French Frog

Atook

  • Swamp Rat
  • Posts: 1027
  • AKA Tim
Re: Deleting XData: Don't Delete the registered app(1001) TypedValue.
« Reply #4 on: August 09, 2016, 03:35:21 PM »
Thanks Gile! That did the trick. It's always good to cut code out of overly complex functions. Here's the solution I'm running so far.
Code - C#: [Select]
  1. /// <summary>
  2. /// Deletes xdata under the regsitered app specified.
  3. /// </summary>
  4. /// <param name="objID">The object identifier.</param>
  5. /// <param name="appName">name of the registered app to delete</param>
  6. public static void DeleteXData(ObjectId objID, string appName)
  7. {
  8.         if (appName.Length<1) return;
  9.         using (LockedTransaction acTr = Active.Document.TransactionManager.StartLockedTransaction())
  10.         {
  11.                 // this RB deletes any data under the registered app
  12.                 ResultBuffer deleteData = new ResultBuffer(new TypedValue(CODE_APPNAME,appName));
  13.                 DBObject obj = acTr.GetObject(objID, OpenMode.ForWrite);
  14.                 // register the app, even though it's being deleted. If not registered throws an appnotregistered error
  15.                 RegisterApps(deleteData);
  16.                 obj.XData=deleteData;
  17.                 acTr.Commit();
  18.         }
  19. }
  20.  

I guess there's a bunch of checking done behind the scenes of obj.XData =