It wasn't as easy as it first appeared. Here is a quote from an ESRI staff member that replied to my plea for help in the forums:
DockableWindow is a bit tricky here since it is implemented by two classes - 1) the UI part is the designer surface derived from controls and 2) the non-UI part is the class actually inherits from DockableWindow base class.
FromID can only handle types derived from base classes declared in ESRI.ArcGIS.Desktop.AddIns.dll. You have to pass in the type that inherits DockableWindow, which is the inner class of the designer window itself if you are using the Add-in Wizard.
If you go to the xml declaration of the dockable window, you will see the class attribute is set to “DockableWindow1+AddinImpl”. You have to pass this type to get the dockablewindow implementation class first, then you have to expose a property there get a hold of the UI window.While I won't pretend to understand stand it perfectly yet, I did come up with a solution that works well.
First, I added added a property called "UI" to the innerclass "AddinImpl" within my dockable window class that points to the dockable window class (why isn't this part of the template?):
/// <summary> /// Implementation class of the dockable window add-in. It is responsible for /// creating and disposing the user interface class of the dockable window. /// </summary> public class AddinImpl : ESRI.ArcGIS.Desktop.AddIns.DockableWindow { private DockableWindow1 m_windowUI; // this property is what I added - the rest was generated by the template internal DockableWindow1 UI { get { return m_windowUI; } } public AddinImpl() { } protected override IntPtr OnCreateChild() { m_windowUI = new DockableWindow1(this.Hook); return m_windowUI.Handle; } protected override void Dispose(bool disposing) { if (m_windowUI != null) m_windowUI.Dispose(disposing); base.Dispose(disposing); } }
Then to get the dockable window from another class it was just a few lines:
// get reference to dockable window DockableWindow1.AddinImpl winImpl = AddIn.FromID<DockableWindow1.AddinImpl>(ThisAddIn.IDs.DockableWindow1); DockableWindow1 dockWin = winImpl.UI; // or you could just do this DockableWindow1 dockWin = AddIn.FromID<DockableWindow1.AddinImpl>(ThisAddIn.IDs.DockableWindow1).UI;
I spent hours trying to figure this out. Hopefully this will save you the head-ache. Anyone else out there using Add-ins yet?
Thanks so much, that just saved my day !! :)
ReplyDeleteThank you very much ... I spent the whole day with this problem. I tried to find the way to access UserData as in ArcGIS 9.3. You saved the timeline of my project.
ReplyDeleteLet me add my thanks to the list.
ReplyDeletethanks for this, but I could could not add items to my list box in Docwindow from any other class !!!! why this is not possible?
ReplyDeleteregards
Rajesh
rrajeshh.blogspot.com
Exactly what I was looking for! Thanks for posting it.
ReplyDeleteI owe you one. WHY IS THIS NOT IN THE DOCUMENTATION ESRI!????
ReplyDeleteThank You!!!
ReplyDeletehttp://i695.photobucket.com/albums/vv311/JVPB1/icecoldbeer344.jpg
Thanks. I then ran into the problem that once closed I could never bring the Dockable Window back again!!
ReplyDeleteAnyway, I did this....
I added the following to my UserControl (in between the Hook and the internal class).
private UIDClass _uid = null;
public UID UID
{
get
{
if (_uid == null)
{
_uid = new UIDClass();
_uid.Value = ThisAddIn.IDs.RoadCATMainDockableWindow;
}
return _uid;
}
}
public IDockableWindow DockableWindow
{
get
{
return ArcMap.DockableWindowManager.GetDockableWindow(UID);
}
}
Then you have all the IDockableWindow stuff available to you - very useful (like your_win_dock_obj.DockableWindow.Dock(esriDockFlags.esriDockShow) ).
Took me a while to work out how to get a docked window to show again! Or did I miss something obvious here??
I have dockable window in ArcCatalog Add-Ins. Do you know how would I make that dockable window available to ArcMap Add-Ins ?
ReplyDeleteBig Super Thank You here! I had been fighting with this one, so far, this is the only straight forward answer to this problem.
ReplyDeleteYou rock!
You're welcome!
DeleteHave you tried this with WPF? In WPF, m_windowUI is of type ElementHost and DocableWindow1 is a child created off of it. I am struggling with getting hold of DockableWindow there.
ReplyDeleteNo, I haven't tried it in WPF. I've gotten away from .NET development in the last few years. Maybe someone else has ideas?
DeleteVery helpful, thanks for sharing!
ReplyDeleteMany Thanks! This was not obvious and would have taken lots of time to figure out.
ReplyDeleteGreat post Scott.
ReplyDeleteAnon@Sept 4th I am trying to work with support to determine how to do this correctly in WPF; I cannot figure it out.
I have resorted in the past to finding the dockWin from... inside the dockWin class:
'run from a button inside the dockWin to save and close it. save code not included.
'where my dock win is called attributeWindow
If attributeWindow Is Nothing Then
Dim attributeWindowID As UID = New UIDClass()
attributeWindowID.Value = My.ThisAddIn.IDs.attributeWindow
attributeWindow = My.ArcMap.DockableWindowManager.GetDockableWindow(attributeWindowID)
End If
attributeWindow.Show(False)
'end code
but it seems ridiculous I have to find by name, the instance of the class I am in. I was hoping Me.Show(False) would close the window :)
I also tried a DirectCast(Me, IDockableWindow).Show(False) but again it's not a dockWin it's an ElementHost.
Very annoying, this should be dirt easy.
Cheers
Tom
Good luck with that. I do almost exclusively javascript development now so I'm afraid I'm not much help.
DeleteThank you very much. You saved my day.
ReplyDeleteThank you very much!
ReplyDeleteplease help, how can i make this dockable window non resizable.
ReplyDeletehere is my complete post
https://geonet.esri.com/thread/166202
Please help me in above issue. Thanks
DeleteHi Scott. Thank you very much for this post. I got a couple of headaches trying to figure this out using ESRI's resources. Really shaking my head about why your method is not how ESRI implemented it in the first place, as it lets you access the dockable window like a windows form. My ArcGIS addins are MUCH more robust now with far fewer headaches. I had been using timers and user settings to exchange data.
ReplyDeleteFor anyone still stuck, I followed Scott's instructions to the letter. Where I deviated is that I first declared (but did not initialize) the dockable window as an instance variable (accessible everywhere) in the tool I was calling the window from:
public class Tool_AddProject : ESRI.ArcGIS.Desktop.AddIns.Tool
{
DockableWindow_Projects dockWin;
DockableWindow_Projects.AddinImpl winImpl;
, and then initialized it as he indicated in the tool's constructor (sorry about the formatting):
public Tool_AddPoint()
{
winImpl = AddIn.FromID (ThisAddIn.IDs.DockableWindow_Projects);
dockWin = winImpl.UI;
dockWin.Show();
By declaring it first, you can access the dockable window from any method in your tool class. Scott's method is a significant improvement over using the UserData object (which, admittedly, I never figured out).
please help, how can i make this dockable window non resizable.
ReplyDeletehere is my complete post
https://geonet.esri.com/thread/166202
Probably too late to help anybody but just in case I was able to do this using wpf dockable window. I accomplished this by changing "private System.Windows.Forms.Integration.ElementHost m_windowUI; ' to 'public System.Windows.Forms.Integration.ElementHost m_windowUI; ' in the user control declaration.
ReplyDeleteI then was able to get the dockable user control from another class by using:
var winImp = ESRI.ArcGIS.Desktop.AddIns.AddIn.FromID(ThisAddIn.IDs.CurrentSheet);
CurrentSheet cs = (AssessorEditTools.CurrentSheet)winImp.m_windowUI.Child;
This comment has been removed by the author.
ReplyDelete