Revit 2023. Attempting to batch join wall and floors, using "DialogBoxShowingEventArgs" to suppress this warning by setting the override result to commandlink1, or unjoin elements.
the code thus far:
namespace Batch_Switch_Join_Order
{
[Transaction(TransactionMode.Manual)]
public class BatchSwitcherooo : IExternalCommand
{
public Result Execute(ExternalCommandData commdata, ref string msg, ElementSet elemset)
{
UIApplication _uiapp = commdata.Application;
UIDocument _uidoc = commdata.Application.ActiveUIDocument;
Document _doc = _uidoc.Document;
_uiapp.DialogBoxShowing += new EventHandler<DialogBoxShowingEventArgs>(Dialogboxshower);
List<Element> walls = new FilteredElementCollector(_doc).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType().ToList();
List<Element> floors = new FilteredElementCollector(_doc).OfCategory(BuiltInCategory.OST_Floors).WhereElementIsNotElementType().ToList();
using (TransactionGroup trg = new TransactionGroup(_doc))
{
trg.Start("theJoining");
foreach (Element wall in walls)
{
foreach (Element floor in floors)
{
using (Transaction tr = new Transaction(_doc))
{
tr.Start("Joining");
try
{
JoinGeometryUtils.JoinGeometry(_doc, wall, floor);
//JoinGeometryUtils.SwitchJoinOrder(_doc, wall, floor);
tr.Commit();
}
catch
{
tr.RollBack();
}
}
}
}
trg.Assimilate();
}
return Result.Succeeded;
}
private void Dialogboxshower(object sender, DialogBoxShowingEventArgs e)
{
string s = e.DialogId.ToString();
if (e.DialogId.Equals("Dialog_Revit_DocWarnDialog"))
{
e.OverrideResult((int)TaskDialogResult.CommandLink1);
}
}
}
}
Now, this is working fine, however, theres a nasty "regen flicker" each time, see attached GIF. Ive tried getting at it as a TaskDialog and MessageDialog, both return null. FailureProcessor registers it, but FailuresAccessor.GetFailureMessages() returns empty, so nothing more i could do with that. Could be with how im structuring the nested transactions/for loops? Thoughts?
Solved! Go to Solution.
Revit 2023. Attempting to batch join wall and floors, using "DialogBoxShowingEventArgs" to suppress this warning by setting the override result to commandlink1, or unjoin elements.
the code thus far:
namespace Batch_Switch_Join_Order
{
[Transaction(TransactionMode.Manual)]
public class BatchSwitcherooo : IExternalCommand
{
public Result Execute(ExternalCommandData commdata, ref string msg, ElementSet elemset)
{
UIApplication _uiapp = commdata.Application;
UIDocument _uidoc = commdata.Application.ActiveUIDocument;
Document _doc = _uidoc.Document;
_uiapp.DialogBoxShowing += new EventHandler<DialogBoxShowingEventArgs>(Dialogboxshower);
List<Element> walls = new FilteredElementCollector(_doc).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType().ToList();
List<Element> floors = new FilteredElementCollector(_doc).OfCategory(BuiltInCategory.OST_Floors).WhereElementIsNotElementType().ToList();
using (TransactionGroup trg = new TransactionGroup(_doc))
{
trg.Start("theJoining");
foreach (Element wall in walls)
{
foreach (Element floor in floors)
{
using (Transaction tr = new Transaction(_doc))
{
tr.Start("Joining");
try
{
JoinGeometryUtils.JoinGeometry(_doc, wall, floor);
//JoinGeometryUtils.SwitchJoinOrder(_doc, wall, floor);
tr.Commit();
}
catch
{
tr.RollBack();
}
}
}
}
trg.Assimilate();
}
return Result.Succeeded;
}
private void Dialogboxshower(object sender, DialogBoxShowingEventArgs e)
{
string s = e.DialogId.ToString();
if (e.DialogId.Equals("Dialog_Revit_DocWarnDialog"))
{
e.OverrideResult((int)TaskDialogResult.CommandLink1);
}
}
}
}
Now, this is working fine, however, theres a nasty "regen flicker" each time, see attached GIF. Ive tried getting at it as a TaskDialog and MessageDialog, both return null. FailureProcessor registers it, but FailuresAccessor.GetFailureMessages() returns empty, so nothing more i could do with that. Could be with how im structuring the nested transactions/for loops? Thoughts?
Solved! Go to Solution.
Solved by Moustafa_K. Go to Solution.
the DialogBoxShowingEventArgs is triggered when the dialog is about to be shown, and not to hold the showing process. depending on the speed of the GPU and the processor the flicker might be expected.
I am using different implementation to avoid such window flicker using the IFailuresPreprocessor Handler. the implementation is straight forward. see the example already there in the documentation. in your case the failure IDs would be one of these 2 Ids, or may be both.
BuiltInFailures.JoinElementsFailures.JoiningDisjointWarn,
BuiltInFailures.JoinElementsFailures.JoiningDisjoint,
You can add these failure process to the Transaction. see this implementation:
public void JoinElements(Element e1, Element e2)
{
var trans = new Transaction(e1.Document, "Join");
var failop = trans.GetFailureHandlingOptions();
failop.SetFailuresPreprocessor(new JoinWarningSwallower());
trans.SetFailureHandlingOptions(failop);
trans.Start();
JoinGeometryUtils.JoinGeometry(Doc, e1, e2);
trans.Commit();
}
public class JoinWarningSwallower : IFailuresPreprocessor
{
public FailureProcessingResult PreprocessFailures(FailuresAccessor failuresAccessor)
{
IList<FailureMessageAccessor> failList = new List<FailureMessageAccessor>();
// Inside event handler, get all warnings
failList = failuresAccessor.GetFailureMessages();
foreach (FailureMessageAccessor failure in failList)
{
// check FailureDefinitionIds against ones that you want to dismiss,
FailureDefinitionId failID = failure.GetFailureDefinitionId();
// prevent Revit from showing Unenclosed room warnings you can ignore the if so,
// it can delete any warning occurs, if you are sure
// you know what are you are doing.
if (
failID == BuiltInFailures.JoinElementsFailures.JoiningDisjoint
|| failID == BuiltInFailures.JoinElementsFailures.JoiningDisjointWarn
)
{
failuresAccessor.DeleteWarning(failure);
}
}
return FailureProcessingResult.Continue;
}
}
the DialogBoxShowingEventArgs is triggered when the dialog is about to be shown, and not to hold the showing process. depending on the speed of the GPU and the processor the flicker might be expected.
I am using different implementation to avoid such window flicker using the IFailuresPreprocessor Handler. the implementation is straight forward. see the example already there in the documentation. in your case the failure IDs would be one of these 2 Ids, or may be both.
BuiltInFailures.JoinElementsFailures.JoiningDisjointWarn,
BuiltInFailures.JoinElementsFailures.JoiningDisjoint,
You can add these failure process to the Transaction. see this implementation:
public void JoinElements(Element e1, Element e2)
{
var trans = new Transaction(e1.Document, "Join");
var failop = trans.GetFailureHandlingOptions();
failop.SetFailuresPreprocessor(new JoinWarningSwallower());
trans.SetFailureHandlingOptions(failop);
trans.Start();
JoinGeometryUtils.JoinGeometry(Doc, e1, e2);
trans.Commit();
}
public class JoinWarningSwallower : IFailuresPreprocessor
{
public FailureProcessingResult PreprocessFailures(FailuresAccessor failuresAccessor)
{
IList<FailureMessageAccessor> failList = new List<FailureMessageAccessor>();
// Inside event handler, get all warnings
failList = failuresAccessor.GetFailureMessages();
foreach (FailureMessageAccessor failure in failList)
{
// check FailureDefinitionIds against ones that you want to dismiss,
FailureDefinitionId failID = failure.GetFailureDefinitionId();
// prevent Revit from showing Unenclosed room warnings you can ignore the if so,
// it can delete any warning occurs, if you are sure
// you know what are you are doing.
if (
failID == BuiltInFailures.JoinElementsFailures.JoiningDisjoint
|| failID == BuiltInFailures.JoinElementsFailures.JoiningDisjointWarn
)
{
failuresAccessor.DeleteWarning(failure);
}
}
return FailureProcessingResult.Continue;
}
}
@Moustafa_Kyup that did the trick, thanks. In summation, for the curious: Implementing IFailuresPreProcessor, and attaching it to the transaction, rather than FailuresProcceingEventArgs as an event handler is the solution.
Revised code attached, i had to nuke the Try/Catch as it was saying the transaction had not started yet:
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
namespace Batch_Switch_Join_Order
{
[Regeneration(RegenerationOption.Manual)]
public class BatchSwitcherooo : IExternalCommand
{
public Result Execute(ExternalCommandData commdata, ref string msg, ElementSet elemset)
{
UIApplication _uiapp = commdata.Application;
UIDocument _uidoc = commdata.Application.ActiveUIDocument;
Document _doc = _uidoc.Document;
List<Element> walls = new FilteredElementCollector(_doc).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType().ToList();
List<Element> floors = new FilteredElementCollector(_doc).OfCategory(BuiltInCategory.OST_Floors).WhereElementIsNotElementType().ToList();
using (TransactionGroup trg = new TransactionGroup(_doc))
{
trg.Start("theJoining");
foreach (Element wall in walls)
{
using (Transaction tr = new Transaction(_doc))
{
var failop = tr.GetFailureHandlingOptions();
failop.SetFailuresPreprocessor(new FailSauce());
tr.SetFailureHandlingOptions(failop);
tr.Start("Joining");
foreach (Element floor in floors)
{
JoinGeometryUtils.JoinGeometry(_doc, wall, floor);
JoinGeometryUtils.SwitchJoinOrder(_doc, wall, floor);
}
tr.Commit();
}
}
trg.Assimilate();
}
return Result.Succeeded;
}
}
public class FailSauce : IFailuresPreprocessor
{
public FailureProcessingResult PreprocessFailures(FailuresAccessor failaccess)
{
foreach (FailureMessageAccessor failmsg in failaccess.GetFailureMessages())
{
FailureDefinitionId failid = failmsg.GetFailureDefinitionId();
if (failid == BuiltInFailures.JoinElementsFailures.JoiningDisjoint ^ failid == BuiltInFailures.JoinElementsFailures.JoiningDisjointWarn)
{
failaccess.DeleteWarning(failmsg);
}
}
return FailureProcessingResult.Continue;
}
}
}
@Moustafa_Kyup that did the trick, thanks. In summation, for the curious: Implementing IFailuresPreProcessor, and attaching it to the transaction, rather than FailuresProcceingEventArgs as an event handler is the solution.
Revised code attached, i had to nuke the Try/Catch as it was saying the transaction had not started yet:
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
namespace Batch_Switch_Join_Order
{
[Regeneration(RegenerationOption.Manual)]
public class BatchSwitcherooo : IExternalCommand
{
public Result Execute(ExternalCommandData commdata, ref string msg, ElementSet elemset)
{
UIApplication _uiapp = commdata.Application;
UIDocument _uidoc = commdata.Application.ActiveUIDocument;
Document _doc = _uidoc.Document;
List<Element> walls = new FilteredElementCollector(_doc).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType().ToList();
List<Element> floors = new FilteredElementCollector(_doc).OfCategory(BuiltInCategory.OST_Floors).WhereElementIsNotElementType().ToList();
using (TransactionGroup trg = new TransactionGroup(_doc))
{
trg.Start("theJoining");
foreach (Element wall in walls)
{
using (Transaction tr = new Transaction(_doc))
{
var failop = tr.GetFailureHandlingOptions();
failop.SetFailuresPreprocessor(new FailSauce());
tr.SetFailureHandlingOptions(failop);
tr.Start("Joining");
foreach (Element floor in floors)
{
JoinGeometryUtils.JoinGeometry(_doc, wall, floor);
JoinGeometryUtils.SwitchJoinOrder(_doc, wall, floor);
}
tr.Commit();
}
}
trg.Assimilate();
}
return Result.Succeeded;
}
}
public class FailSauce : IFailuresPreprocessor
{
public FailureProcessingResult PreprocessFailures(FailuresAccessor failaccess)
{
foreach (FailureMessageAccessor failmsg in failaccess.GetFailureMessages())
{
FailureDefinitionId failid = failmsg.GetFailureDefinitionId();
if (failid == BuiltInFailures.JoinElementsFailures.JoiningDisjoint ^ failid == BuiltInFailures.JoinElementsFailures.JoiningDisjointWarn)
{
failaccess.DeleteWarning(failmsg);
}
}
return FailureProcessingResult.Continue;
}
}
}
Can't find what you're looking for? Ask the community or share your knowledge.