Revit .NET has provided the Drag & Drop API (UIApplication.DoDragDrop) since version 2013. In this series of posts, we are going to explore the Revit Drag & Drop .NET API (UIApplication.DoDragDrop) case by case.
In this case, let’s merge the Revit project (.rvt file) as dragged & dropped with the current project rather than open the project as the standard drag & drop behaves.
The Revit .NET Drag & Drop API provides another mechanism to support custom drag & drop behavior. More specifically, another signature of the Autodesk.Revit.UI.UIApplication.DoDragDrop() method and the IDropHandler interface come to rescue.
• Add a TextBox to the WPF Window and make it the dragging source.
<TextBox Height="23" Text="C:\TEMP\ToMerge.rvt" HorizontalAlignment="Left" Margin="12,226,0,0" Name="textBox1" VerticalAlignment="Top" Width="254" MouseMove="textBox1_MouseMove" />
• Implement the MouseMove event callback as follows into the Window1 class to make the WPF element as the drag & drop source, the Revit window as the drag & drop target, and our custom drag & drop handler as the action:
private void textBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
MergeProjectDropHandler dropHandler = new MergeProjectDropHandler();
Autodesk.Revit.UI.UIApplication.DoDragDrop((sender as System.Windows.Controls.TextBox).Text, dropHandler);
}
}
• Implement the custom IDropHandler interface as follows:
public class MergeProjectDropHandler : Autodesk.Revit.UI.IDropHandler
{
public class IgoreDuplicateTypeNames : IDuplicateTypeNamesHandler
{
public DuplicateTypeAction OnDuplicateTypeNamesFound(DuplicateTypeNamesHandlerArgs args)
{
return DuplicateTypeAction.UseDestinationTypes;
}
}
public void Execute(Autodesk.Revit.UI.UIDocument document, object data)
{
using (Autodesk.Revit.DB.Document doc = document.Application.Application.OpenDocumentFile((string)data))
{
using (Autodesk.Revit.DB.Transaction trans = new Autodesk.Revit.DB.Transaction(document.Document, "MergeProjectsByDragNDrop"))
{
trans.Start();
CopyPasteOptions cpOpts = new CopyPasteOptions();
cpOpts.SetDuplicateTypeNamesHandler(new IgoreDuplicateTypeNames());
foreach (BuiltInCategory biCat in Enum.GetValues(typeof(BuiltInCategory)))
{
FilteredElementCollector finalCollector = new FilteredElementCollector(doc);
try
{
ICollection<ElementId> ids = finalCollector.WherePasses(new ElementCategoryFilter(biCat)).ToElementIds();
if (ids.Count > 0)
ElementTransformUtils.CopyElements(doc, ids, document.Document, Autodesk.Revit.DB.Transform.Identity, cpOpts);
}
catch { }
}
trans.Commit();
}
}
}
}
• Make sure the following code is still in the Execute of the external command class:
Window1 win = new Window1();
win.Show();
In case wondering about the category filtering code and element copying code are wrapped into a try/catch block, please refer to earlier posts for details. The basic idea is that they may fail for some categories and elements without good a reason.
In our case, the current Revit project has some columns only and the external model has some walls. After the projects being merged through the drag & drop from the newly added TextBox into the WPF sample window, the current model may look something as follows.
Revit Addin Wizard (RevitAddinWizard) provides various wizards, coders and widgets to help program Revit addins. It can be downloaded from the Download link at the bottom of the blog index page.