There are no obvious reasons that the Revit 2011 API does not support or the Revit 2011 product does not adopt the powerful UI technology checking from two facts: the API is built upon the Microsoft .NET Framework 3.5 in which all WPF components are packaged and the Revit Ribbons apparently are internally created using the same WPF technology.
The only thing left is that we have to dig out some details and work around some issues by ourselves.
The biggest barrier is that the Window (WPF) template (not as the Windows Form one) is not directly available for a Class Library type project. If we add a new item into the Revit Addin project of concern, which is created either manually or automatically using the RevitAddinWizard, under the WPF node of the Add New Item dialog, we can only see the User Control (WPF) template in the IDE of Visual Studio 2008.
On the other hand, if we create a WPF Application type project from scratch and switch the project type to Class Library, some compiling error will come up, e.g. “Library project file cannot specify ApplicationDefinition element.” And the most annoying part is that even if we can resolve the error through some means we have to add all those Revit Addins’ stuffs manually, like assembly references, namespaces, skeletons of external applications and commands, ribbon creation, hookup among those ribbon buttons, external applications and external commands, resource management code, and so on.
Ouch! I do not believe people would like to do so if having other choices.
The limitation from Microsoft Visual Studio side is odd. Why does it not allow a WPF Window be added to a Class Library project through its IDE to make Revit developers’ life a bit easier?
Anyway, do not worry. We find something out simple and working.
We follow the following path to create a new User Control (WPF) and name it as UserControl1.XAML, for example:
New Item
->WPF
->User Control (WPF)
For simplicity, only one button is added to the WPF user control through either dragging and dropping as before with Window Forms or editing the XAML directly.
<UserControl x:Class="RevitAddinCSWPF.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">
<Grid>
<Button Margin="42,116,45,149" Name="button1" Click="button1_Click">Helllo from WPF</Button>
</Grid>
</UserControl>
Now double click the button and implement its callback like:
private void button1_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Hello friends! I am from the WPF world!");
}
Next, we create a WPF window on the fly and hoop up it and the WPF user control together through the simple and functional Content property in the Execute() callback of the external command we care. If it is created by the RevitAddinWizard, the good place to put the code is below the TODO comment, like:
//TODO: add your code below.
UserControl1 userControl = new UserControl1();
Window win = new Window();
win.Content = userControl;
win.Show();
Before building the addin project, we have to make one more little tweak. Due to the fact that the PresentationFramework assembly reference has been introduced into the project automatically by the WPF User Control item creation and its namespace System.Windows has the same MessageBox type now as the WinForm System.Windows.Forms, an ambiguous error message will be generated for the simple MessageBox.Show() call.
After making the type fully qualified like:
System.Windows.Forms.MessageBox.Show
or better commenting out the namespace like:
//using System.Windows.Forms;
the project will compile and build without even a single warning supposing the project is created with the RevitAddinWizard and the above stepps are followed exactly. And better, everything else is ready, e.g. debugging, ribbon panel, ribbon button, resources, command hookup, and more.
Now after Revit is launched, either from inside the Visual Studio IDE by pressing F5 or outside of it, one more ribbon panel will appear under the Add-Ins ribbon tab. Supposing the project is named as RevitAddinCSWPF, the new ribbon panel and button will show up.
If the ExtCmd button is clicked, a WPF window will show up, as we expected. And better, the window icon has been set as the default Revit TaskDialog one automatically.
If the button is pressed, the test addin will say hi and introduce itself a bit.
So, it proves the concept clearly, showing a WPF window in addins of Revit using the Revit 2011 API and newer is not a problem at all.
More details can be found from WPF and Revit Addin/API: Popup WPF Window from External Command Using C# and Revit API.