It's because they're dictionary entries and they aren't hard owned by default. Groups don't survive a wblock do they...
I remember reading some little tidbit of info in the ARX docs to support this, hence, when code copies them over, it gives them anonymous 'keys' in the dictionary.
Here is one way of copying them over.Note that I probably could have responded to the endDeepClone event instead of this:
public static bool ImportPageSetups(Document doc) {
// Do we have our template dbase?
if (_batchPageSetupTemplate == null)
return false; // Nope - bail out immediately!
// Get a pointer to the current doc's dbase...
Database curDb = doc.Database;
// Declare 2 transaction objects - one for each dbase...
Transaction curDbTr = null;
Transaction psDbTr = null;
Transaction psRenameTr = null;
// Objectid collection to hold the pagesetups we're going to clone...
ObjectIdCollection psIds = new ObjectIdCollection();
IdMapping psIdMap = null;
using (DocumentLock docLock = doc.LockDocument()) {
// Using a try/finally construct here as it's neater than
// trying to nest multiple using statements.
try {
// Kick off the transaction on the template dbase...
psDbTr = _batchPageSetupTemplate.TransactionManager.StartTransaction();
// ...also, kick off a trtansaction on the current dbase as well...
curDbTr = curDb.TransactionManager.StartTransaction();
// Open up the PlotSettings Dictionary on both dbase's...
DBDictionary curDbPsDict = (DBDictionary)curDbTr.GetObject(curDb.PlotSettingsDictionaryId, OpenMode.ForRead);
DBDictionary psDbPsDict = (DBDictionary)psDbTr.GetObject(_batchPageSetupTemplate.PlotSettingsDictionaryId, OpenMode.ForRead);
// Loop over the plot settings dictionary in the template and
// try to get the same entry in the current drawing.
// If we DO get it, erase it...
foreach (System.Collections.DictionaryEntry psDbPs in psDbPsDict) {
// Get the name...
string psName = (string)psDbPs.Key;
// Does it exist in our current dbase?
if (curDbPsDict.Contains(psName)) {
// Get it...
ObjectId curDbPsId = curDbPsDict.GetAt(psName);
// open it up...
PlotSettings curDbPs = (PlotSettings)curDbTr.GetObject(curDbPsId, OpenMode.ForWrite);
// Erase it...
curDbPs.Erase();
// Add this page setup object id into our collection of objects to clone...
psIds.Add((ObjectId)psDbPs.Value);
} else
psIds.Add((ObjectId)psDbPs.Value);
}//foreach
// OK, we now should have our list of objectid's to clone, but to be
// safe we check...
if (psIds.Count == 0)
return false;
// Got id's, so clone 'em
psIdMap = curDb.WblockCloneObjects(psIds, curDb.PlotSettingsDictionaryId, DuplicateRecordCloning.Ignore, false);
// Commit the transaction on our current dbase - we can abort the
// one on the template as we're not doing anything...
curDbTr.Commit();
// We need to commit the last transaction, above, and start a new one,
// as I suspect the cloned objects id's are in flux inside the above transaction,
// and we can't reliably access them.
psRenameTr = curDb.TransactionManager.StartTransaction();
DBDictionary dbDict = (DBDictionary)psRenameTr.GetObject(curDb.PlotSettingsDictionaryId, OpenMode.ForWrite);
// OK, we have an idmap, so loop it...
foreach (IdPair psIdPair in psIdMap) {
ObjectId id = psIdPair.Value;
DBObject obj = psRenameTr.GetObject(id, OpenMode.ForRead);
PlotSettings newPs = obj as PlotSettings;
if (newPs == null)
continue;
// Upgrade open...
newPs.UpgradeOpen();
string anonymousName = dbDict.NameAt(id);
// Set the correct name...
dbDict.SetName(anonymousName, newPs.PlotSettingsName);
}
psRenameTr.Commit();
} finally {
if (curDbTr != null)
curDbTr.Dispose();
if (psDbTr != null)
psDbTr.Dispose();
if (psRenameTr != null)
psRenameTr.Dispose();
}
}
return true;
}
Hope this helps.
Cheers,
Glenn.