After making the RAM to Revit tool, I wanted to make a similiar tool, but with ETABs this time.
I learned a lot making the RAM to Revit tool, but also learned a few things that I would like to do differently given the chance.
MVVM Magic
MVVM standards for Model-View-ViewModel and it serves as a way to effectively decouple the user interface (in my case my xaml code) from my data (Model). You do this through creating a ViewModel that allows the model and the view to be completely separate.
I will admit, I am speaking like I know what this means, but it is still somewhat of mystery to me, but I think this will prove beneficial in making the ETABs to Revit tool. The amount of coding I spent keeping the UI and the data on the backend "sync"ed up for the R2R tool started to become overwhelming, and it is my understanding that MVVM will be a much cleaner way to keep the data and the view separate.
Below is a gif of the view being dynamically updated with updates that occur in the revit model, really cool stuff. Big thanks to scgq425 on the revit api forums for helping me out with this.
Sample code on github.
Learning Points with MVVM and Revit
I struggled with getting my MVVM code to work because I was using a IEnumerable (does not inherit a lot of the MVVM goodness) when I should have been using an ObservableCollection to store my revit beam data.
public ObservableCollection<RevitFramingModel> StructuralFramingElements { get { return _structuralFramingElements; } set { _structuralFramingElements = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(StructuralFramingElements))); } }
I also struggled with trying to trigger the data to update when a change is performed in the revit document. After searching the revit api documentation, it seemed like the IUpdater interface would do the trick. From the revit documentation:
IUpdater Interface - The interface used to create an updater capable of reacting to changes in the Revit model.
I wanted to react to changes to my beams, so I thought this would do the trick. Throwing the IUpdater interface in the my View Model, my code seemed to be working.
public class StructuralFramingUpdater : IUpdater { static AddInId m_appId; static UpdaterId m_updaterId; private readonly MainViewModel _mainViewModel; public StructuralFramingUpdater(AddInId id, MainViewModel mainViewModel) { m_appId = id; m_updaterId = new UpdaterId(m_appId, new Guid("FBFBF6B2-4C06-42d4-97C1-D1B4EB593EFF")); _mainViewModel = mainViewModel; } public void Execute(UpdaterData data) { ObservableCollection<RevitFramingModel> structuralFramingElements = _mainViewModel.StructuralFramingElements; // Check if the modified element is a structural framing element foreach (ElementId elementId in data.GetModifiedElementIds()) { Element element = data.GetDocument().GetElement(elementId); if (element != null && element.Category.Name == "Structural Framing") { // Update the corresponding RevitFramingModel RevitFramingModel framingModel = structuralFramingElements.FirstOrDefault(m => m.Id == element.UniqueId); if (framingModel != null) { framingModel.Name = element.Name; } } } _mainViewModel.StructuralFramingElements = structuralFramingElements; } public string GetAdditionalInformation() { return "Structural Framing Updater: updates structural framing models when changes occur"; } public ChangePriority GetChangePriority() { return ChangePriority.Annotations; } public UpdaterId GetUpdaterId() { return m_updaterId; } public string GetUpdaterName() { return "Structural Framing Updater"; } }
I used chatgpt to write a lot of this code, it was funny to see that chatgpt was essentially "copying" this portion of the web:
https://help.autodesk.com/view/RVT/2022/ENU/?guid=Revit_API_Revit_API_Developers_Guide_Advanced_Topics_Dynamic_Model_Update_Implementing_IUpdater_html
I noticed the the Guid between both programs was identical, pretty funny.
Modeless Mayhem
The next item I wanted to solve with the R2R tool was the lack interactiveness, when the popup window for R2R begins, you are not able to interact with your revit model. This is a huge downside that I want to come back to, but for now, I wanted to make sure the E2R would not be limited in the same way.
The fix to make the window "modeless", switching the popup window from
mainWindow.ShowDialog(); to mainWindow.Show();
This simple little change did the trick. I think making the full fledged E2R tool modeless will be more complicated than this moving forward with multiple windows and popups, but for now, I hopefully optimistic that I can keep this application modeless with little coding brainpower spent.
ETABs to Revit tool coming soon...
???