Cancel IExternalCommand?
Is it possible to let user cancel an IExternalCommand for example by pressin Escape key? Command below lists all types in the current model, however in some models it can freeze revit for a few minutes. If that happens user should be able to cancel the operation.
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.Attributes;
using System.Collections.Generic;
using System.Linq;
[Transaction(TransactionMode.Manual)]
public class ListTypesInCurrentModel : IExternalCommand
{
public Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements)
{
UIDocument uidoc = commandData.Application.ActiveUIDocument;
Document doc = uidoc.Document;
// Step 1: Collect all families in the document
var allFamilies = new FilteredElementCollector(doc)
.OfClass(typeof(Family))
.Cast<Family>()
.ToList();
// Step 2: Prepare a list of type entries with family, type, and category information
List<Dictionary<string, object>> typeEntries = new List<Dictionary<string, object>>();
foreach (Family family in allFamilies)
{
// Get all types associated with the family
var familySymbols = new FilteredElementCollector(doc)
.OfClass(typeof(FamilySymbol))
.OfCategoryId(family.FamilyCategoryId)
.Cast<FamilySymbol>()
.Where(symbol => symbol.FamilyName == family.Name) // Match by family name
.ToList();
foreach (var familySymbol in familySymbols)
{
var entry = new Dictionary<string, object>
{
{ "Type Name", familySymbol.Name },
{ "Family", family.Name },
{ "Category", familySymbol.Category.Name },
{ "Type Element", familySymbol } // Store the element type for selection
};
typeEntries.Add(entry);
}
}
// Step 3: Display the list of types using the CustomGUIs.DataGrid method
var propertyNames = new List<string> { "Type Name", "Family", "Category" }; // Display only relevant columns
var selectedEntries = CustomGUIs.DataGrid(typeEntries, propertyNames, spanAllScreens: false);
if (selectedEntries.Count == 0)
{
return Result.Cancelled; // No selection made
}
// Step 4: Collect ElementIds of the selected types
List<ElementId> selectedTypeIds = selectedEntries
.Select(entry => (entry["Type Element"] as Element).Id)
.ToList();
// Step 5: Collect all instances of the selected types in the model
var selectedInstances = new FilteredElementCollector(doc)
.WherePasses(new ElementMulticlassFilter(new List<System.Type> { typeof(FamilyInstance), typeof(ElementType) }))
.Where(x => selectedTypeIds.Contains(x.GetTypeId()))
.Select(x => x.Id)
.ToList();
// Step 6: Select the instances in the model
uidoc.Selection.SetElementIds(selectedInstances);
return Result.Succeeded;
}
}
Link copied