We demonstrated creating a WPF Window from an External Command of Revit Addins before either through creating a WPF window on the fly and hosting a User Control into it or through converting a WPF Application project to a Revit Class Library then creating a WPF window from an XMAL template directly.
We also made the created-on-the-fly WPF window/control look good through tweaking many properties of both the host window and the hosted control and added some fancy effects to both the background of the window/control and a particular button.
A cool feature about WPF is that we can make the same user control/window and its buttons look different but all cool, or have different nice skins at different times. We can achieve the goal through applying a theme to the whole WPF user control or window.
We can apply themes in many ways. The themes can be from some external loose XMAL files or from some internal compiled/embedded theme XMAL resources either in the same assembly or in separate ones. And we can statically specify the theme for the WPF Control/Window in the XMAL files or dynamically merge the theme definitions into its resource dictionaries with code.
We are going to add some skin to the User Control that we have demonstrated before through specifying a theme provided by the .NET Framework itself, more specifically the PresentationFramework.Luna.
The .NET Framework 3.0 provides a few theme assemblies such as PresentationFramework.Aero, PresentationFramework.Classic, PresentationFramework.Luna and PresentationFramework.Royale. We will be demonstrating how to apply the PresentationFramework.Luna theme to our WPF user control (window).
The assembly has to be referenced into the project first:
Now we add the theme Source as a ResourceDictionary to the MergedDictionaries of the ResourceDictionary of the Resources of the UserControl. The URI source path is pretty similar to that of an embedded theme in the host assembly itself. Only the assembly name is the WPF Presentation Framework theme assembly now, PresentationFramework.Luna, as the highlighted code in the following UserControl XMAL definition file shows:
<UserControl x:Class="RevitAddinCSWPF.UserControl3"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/PresentationFramework.Luna;component/themes/luna.normalcolor.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Rectangle Width="Auto" Height="Auto">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="Azure" Offset="0.0" />
<GradientStop Color="Orchid" Offset="0.15" />
<GradientStop Color="Purple" Offset="0.25" />
<GradientStop Color="RosyBrown" Offset="0.5" />
<GradientStop Color="Purple" Offset="0.75" />
<GradientStop Color="Orchid" Offset="0.85" />
<GradientStop Color="Azure" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Button Name="button1" Click="button1_Click" Height="35" Width="200">
<Button.Template>
<ControlTemplate TargetType="Button" >
<Grid Background="#00FFFFFF">
<Ellipse Fill="CadetBlue"/>
<ContentPresenter x:Name="content" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Button.Template>
Hello from WPF
</Button>
<!--<Button Margin="53,49,34,0" Name="button1" Click="button1_Click" Height="35" VerticalAlignment="Top">Hello from WPF</Button>-->
<Button Height="27" HorizontalAlignment="Left" Name="button2" VerticalAlignment="Top" Width="24">TL</Button>
<Button Height="27" HorizontalAlignment="Left" Name="button3" VerticalAlignment="Bottom" Width="24">BL</Button>
<Button Height="27" HorizontalAlignment="Right" Name="button4" VerticalAlignment="Top" Width="24">TR</Button>
<Button Height="27" HorizontalAlignment="Right" Name="button5" VerticalAlignment="Bottom" Width="24">BR</Button>
<Button Height="27" HorizontalAlignment="Left" Margin="53,0,0,33" Name="button_Cancel" VerticalAlignment="Bottom" Width="84" Click="button_Cancel_Click">Cancel</Button>
<Button Height="27" HorizontalAlignment="Right" Margin="0,0,34,33" Name="button_OK" VerticalAlignment="Bottom" Width="84" Click="buttonOK_Click">OK</Button>
<CheckBox Height="16" Margin="30,5.52,150,0" Name="checkBox1" VerticalAlignment="Top">CheckBox</CheckBox>
<CheckBox Height="16" Margin="30,27,150,0" Name="checkBox2" VerticalAlignment="Top">CheckBox</CheckBox>
<RadioButton Height="16" Margin="130,5,50,0" Name="radioButton1" VerticalAlignment="Top">RadioButton</RadioButton>
<CheckBox Height="16" Margin="30,49,150,0" Name="checkBox3" VerticalAlignment="Top">CheckBox</CheckBox>
<RadioButton Height="16" Margin="130,27,50,0" Name="radioButton2" VerticalAlignment="Top">RadioButton</RadioButton>
<RadioButton Height="16" Margin="130,49,50,0" Name="radioButton3" VerticalAlignment="Top">RadioButton</RadioButton>
</Grid>
</UserControl>
Now the project should build well and we are ready to give it a try immediately by pressing the F5 since Revit Addin Wizard (RevitAddinWizard) has already set up the debugging settings for us automatically.
After the ExtCmd3 ribbon button of the RevitAddinCSWPF ribbon panel is clicked, the WPF Window hosting the User Control shows up with the cool Luna skin this time:
A few check boxes and radio buttons have also been added to the WPF User Control to make the skin effects appear clearer and nicer.
NOTE: In case the Presentation Framework Luna Theme cannot be found by Revit, as indicated by an exception message like the following:
System.Windows.Markup.XamlParseException: '/PresentationFramework.Luna;component/themes/luna.normalcolor.xaml' value cannot be assigned to property 'Source' of object 'System.Windows.ResourceDictionary'. Could not load file or assembly 'PresentationFramework.Luna, Culture=neutral' or one of its dependencies. The system cannot find the file specified. Error at object 'System.Windows.ResourceDictionary' in markup file 'RevitAddinCSWPF;component/usercontrol3.xaml' Line 9 Position 37. ---> System.IO.FileNotFoundException: Could not load file or assembly 'PresentationFramework.Luna, Culture=neutral' or one of its dependencies. The system cannot find the file specified.
File name: 'PresentationFramework.Luna, Culture=neutral'
at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evide...
please find the PresentationFramework.Luna.dll from the .NET Framework installation folder or GAC and copy it over to the Revit Program folder.
There is certainly some more professional way to resolve the assembly lookup issue, but it is not the major concern of this article. By the way, changing the Copy Local of the PresentationFramework.Luna reference from False to True takes no effect due to some unclear reason that Revit will not look for the theme pack in the same folder as the addin resides either.
More articles about WPF and Revit Addin/API can be expected soon. Please stay tuned.
RevitAddinWizard may provide a few coders to address some WPF usage cases in the near future.
Recent Comments