- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hi all,
Building upon the excellent AttributeReferenceOverrule shared by @ActivistInvestor in this thread (my implementation of it shared here for information):
public class AttributeReferenceOverrule : ObjectOverrule
{
static RXClass rxclass = RXObject.GetClass(typeof(AttributeReference));
public AttributeReferenceOverrule()
{
AddOverrule(rxclass, this, true);
}
public override DBObject DeepClone(DBObject dbObject, DBObject ownerObject, IdMapping idMap, bool isPrimary)
{
var result = base.DeepClone(dbObject, ownerObject, idMap, isPrimary);
AttributeReference copy = result as AttributeReference;
if (copy != null)
{
/// TODO: Use additional conditions to decide if this
/// AttributeReference's TextString should be cleared,
/// which could involve any or all of the arguments to
/// this method.
/// In this example, the TextString is cleared unconditionally:
if (!copy.IsWriteEnabled)
copy.UpgradeOpen();
if (copy.Tag == "NearestCornerBlockName" || copy.Tag == "BlockNumber")
{
copy.TextString = string.Empty;
}
}
return result;
}
protected override void Dispose(bool disposing)
{
RemoveOverrule(rxclass, this);
base.Dispose(disposing);
}
}
I thought I would see whether I can achieve similar for BlockReferences. In this case I have two patterns for blockreference names I need to ObjectOverrule the Erase() event for:
(.*)-(.*)-(\d{1,})
And:
(.*)-(.*)-(CR\d{1,})
So I have this:
public class BlockReferenceOverrule : ObjectOverrule
{
static RXClass rxclass = RXObject.GetClass(typeof(BlockReference));
public BlockReferenceOverrule()
{
AddOverrule(rxclass, this, true);
}
public override void Erase(DBObject dbObject, bool erasing)
{
Document doc = CadApp.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
base.Erase(dbObject, erasing);
BlockHelpers blockHelpers = new BlockHelpers();
CadHelper cadHelpers = new CadHelper();
if(dbObject is BlockReference)
{
var blkRef = dbObject as BlockReference;
if (blkRef != null)
{
string blockName = blockHelpers.GetEffectiveName(blkRef);
string pattern = @"(.*)-(.*)-(CR\d{1,})";
var match = Regex.Match(blockName, pattern);
if (match.Success)
{
var ownerId = db.GetLayoutBlockTableRecordId("Model");
if (ownerId.IsNull)
{
CadApp.ShowAlertDialog($"Layout 'Model' not found");
return;
}
using (var tr = db.TransactionManager.StartTransaction())
{
BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject(ownerId, OpenMode.ForWrite);
if (modelSpace != null)
{
var bt = modelSpace.Database.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
var blockRecord = bt[blockName].GetObject(OpenMode.ForWrite) as BlockTableRecord;
if (MessageBox.Show($"Are you sure you want to purge this block?\n{blockName}", "Purge Block",
MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
//purge the block
cadHelpers.PurgeItem(blockRecord.ObjectId);
}
}
tr.Commit();
}
}
}
}
}
protected override void Dispose(bool disposing)
{
RemoveOverrule(rxclass, this);
base.Dispose(disposing);
}
}
Here is the PurgeItem method:
internal void PurgeItem(ObjectId objectId)
{
var doc = AcCoreAp.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
bool itemsPurged = false;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
SymbolTableRecord record = (SymbolTableRecord)tr.GetObject(objectId, OpenMode.ForWrite);
string recordName = record.Name;
ed.WriteMessage("\nPurging " + record.GetType().Name + " " + recordName);
log.Info("Purging " + record.GetType().Name + " " + recordName);
record.Erase();
tr.Commit();
}
}
(having just copied that code there, yes I am aware I can refactor the code in the PurgeItem method into the calling code- I wrote it several months ago but haven't needed it until now so sue me 🤣)
The reasons for the blockreference Erase() objectoverrule are as follows:
- when the user deletes a block that matches the "(.*)-(.*)-(CR\d{1,})" pattern, there is only ever one of them so to save the user a step (and prevent a gap in the numbering since CR blocks increment through system-level-CR# with each new placement) I prompt the user to purge the block so we can reuse that name.
- Find any remaining blockreferences whose names match the "(.*)-(.*)-(\d{1,})" pattern and whose attributereferences contain the name of the CR blockreference and reset them to "".
- Any block that matches the "(.*)-(.*)-(\d{1,})" pattern should erase as normal, and if that blockreference was the last remaining reference, it should again ask if the user wishes to purge that block.
Number 1 is covered by the code I already shared (unless I have missed something blindingly obvious?), but I wondered if anyone has any suggestions for items 2 & 3?
(Having written out item 3 - it seems as simple as checking whether there remain blockreferences in ModelSpace whose name matches the erased blockreference, and if not, then pop the prompt about purging?)
Thanks,
Alex.
Alex Fielder
Inventor Expert
https://github.com/alexfielder/
LinkedIn - Github Inventor Extension Server - Bonkers polygon iLogic thing
Top ten iLogic Tips - API Shortcut In Google Chrome - Assembly Extrusion Example
Solved! Go to Solution.