Just an FYI, if anyone else was looking to solve this problem w/o the use of ElementHost:
I figured this solution with extended reference to the MyAddInWithWPF blog post from a good bit of time ago. I am currently attempting to get this to work as shellview for a Caliburn.Micro development to little success.
With a basic XAML Window:
<Window x:Class="MyAddIn.Views.CalendarDockedWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MyAddIn"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid MaxWidth="500" MaxHeight="300">
<Button Content="Button" Margin="122,198,10,10"/>
<CheckBox Content="CheckBox" Margin="10,183,129,0" VerticalAlignment="Top"/>
<Calendar Margin="10,10,10,52"/>
</Grid>
</Window>
And a related Code-Behind:
public partial class CalendarDockedWindow : Window, IDockableWindow
{
#region /*-------------------- Properties & Fields -------------------------------*/
private readonly string _internalName;
private WindowInteropHelper _helper;
public string InternalName => _internalName;
public WindowInteropHelper Helper => _helper ?? (_helper = new WindowInteropHelper(this));
public IntPtr HWND
{
get
{
Helper.EnsureHandle();
return Helper.Handle;
}
}
#endregion
private CalendarDockedWindow() { InitializeComponent(); }
public CalendarDockedWindow(Inventor.Application app, string clientID, string internalName, string title)
{
_internalName = internalName;
InitializeComponent();
Inventor.UserInterfaceManager _interfaceManager = app.UserInterfaceManager;
var dockableWindow = _interfaceManager.DockableWindows.Add(clientID, internalName, title);
dockableWindow.AddChild(HWND);
WindowStyle = WindowStyle.None;
dockableWindow.DisabledDockingStates = (DockingStateEnum.kDockTop & DockingStateEnum.kDockLeft);
dockableWindow.Caption = title;
dockableWindow.ShowTitleBar = true;
Visibility = Visibility.Visible;
if (dockableWindow.IsCustomized) return;
dockableWindow.Visible = false;
dockableWindow.DockingState = Inventor.DockingStateEnum.kFloat;
dockableWindow.Move(25, 25, dockableWindow.Height, dockableWindow.Width);
}
}
//Simply Interface to ensure
public interface IDockableWindow
{
IntPtr HWND { get; }
string InternalName { get; }
WindowInteropHelper Helper { get; }
}
[Note that Window is the Magic Ingredient] As with a Window object I can get the HWND and assign it as a child to the Dockable Window, this code-behind is heavy and a lot of the work should be done elsewhere, but as a proof of concept it is clear.
I can now create the object with a simple call and collect the window reference in a list to use elsewhere if I need to restrict access or remove based on environment:
private IDockableWindow calendarDockedWindow;
private List< IDockableWindow > dockedWindows = new List< IDockableWindow >();
private void GenerateDockableWindows()
{
calendarDockedWindow = new CalendarDockedWindow( _inventorApplication ,
_addInCLSIDString ,
"MyAddIn:DockedCalendar" ,
"Calendar" );
dockedWindows.Add( calendarDockedWindow );
}