ProGuide Dockpanes - kataya/arcgis-pro-sdk GitHub Wiki
Language: C#
Subject: Framework
Contributor: ArcGIS Pro SDK Team <arcgisprosdk@esri.com>
Organization: Esri, http://www.esri.com
Date: 11/24/2020
ArcGIS Pro: 2.7
Visual Studio: 2017, 2019
This ProGuide explains the step by step process on how to declare a dockpane. However this is for reference only. The recommended approach is to run the dockpane item template.
-
How to declare a dockpane
- Conditions
-
Find a dockpane
-
Customize initial position
-
Customize loading message
- Support Undo/Redo
-
Support drag and drop
- Reset Panes
- Enable contextual help for a dockpane
Dockpanes are modeless dialogs that can be docked at the top, right, left, or bottom of the view area within the application. Dockpanes can also be grouped with other dockpanes and docked relative to each other (that is, below, above, and so on), and can also be undocked and floated. Finally, dockpanes can also be pinned or unpinned so that they slide back into the frame to save space. For each dockpane — each a logical singleton — the framework persists and preserves the docking state so that when shown in subsequent sessions, dockpanes appear in the same positions and in the same state.
The example below shows the declaration of a dockpane. This dockpane specifies a content element that has only a className attribute. When the framework creates the dock pane, it also creates its content class and will set the content’s data context to the dockpane. This automatic binding allows you to use the MVVM pattern when developing dockpanes. For example, a well-designed dockpane will have as little logic as possible in its XAML code behind; instead, all of the controls in the XAML should be bound to properties in the dockpane base class. The dockpane bases classes should be regarded as view-models.
<dockPanes>
<dockPane id="esri_core_TOCDockPane" caption="Contents"
className="TOC.TOCDockPaneViewModel" dock="group"
condition="esri_core_MapPane" dockWith="esri_core_ProjectDockPane">
<content className="TOC.TOCDockPane"/>
</dockPane>
</dockPanes>
Previously, Dockpanes could be established with a condition so that their content only appears when the condition is satisfied. This has now been deprecated.
You can now use WPF Visibility attributes to display or hide controls in the dockpane. Here are couple of samples in the arcgis-pro-sdk-community-samples repo that implement this.
Procedural Symbol Layers With Rule Packages
Construct Marker From Font
Use the following code to find a dockpane (you need the DAML ID):
var pane = FrameworkApplication.DockPaneManager.Find("esri_core_ProjectDockPane");
Use the dock, dockWith, autoHide attributes to set the initial docking state of your dockpane. Dock allows values of left, right, top, bottom, float, or group. Use the dockWith attribute to specify a dockpane that yours is to be positioned relative to.
<dockPanes>
<dockPane id="esri_core_TOCDockPane" caption="Contents"
className="TOC.TOCDockPaneViewModel" dock="left"
condition="esri_core_MapPane">
<content className="TOC.TOCDockPane"/>
</dockPane>
</dockPanes>
<dockPanes>
<dockPane id="esri_core_TOCDockPane" caption="Contents"
className="TOC.TOCDockPaneViewModel" dock="float"
condition="esri_core_MapPane">
<content className="TOC.TOCDockPane"/>
</dockPane>
</dockPanes>
<dockPanes>
<dockPane id="esri_core_TOCDockPane" caption="Contents"
className="TOC.TOCDockPaneViewModel" dock="group" visible="true"
condition="esri_core_MapPane" dockWith="esri_core_projectDockPane">
<content className="TOC.TOCDockPane"/>
</dockPane>
</dockPanes>
During initialization, the framework provides a circular progressor that draws on top of the dockpane window. By default, the progressor displays the loading message as Loading Caption. The loading message can be optionally set in DAML using the delayLoadMessage attribute and updated at runtime.
Pro shows the undo and redo operations associated with the current OperationManager on the Quick Access Toolbar, QAT ( refer to Undo/Redo framework in the ProConcepts Framework). The operations (if any) shown on the Quick Access Toolbar are the operations from the OperationManager associated with the current dockpane or pane that has focus in the application.
public abstract class DockPane : PaneBase, IFrameworkWindow {
...
public virtual OperationManager OperationManager { get; }
...
Each time focus changes, Framework queries the focused dockpane (or pane) OperationManager property for its undo and redo operations for the QAT. In many cases, because Pro panes and dockpanes are usually sharing the same OperationManager associated with the current map or layout, the QAT content does not change with the change in focus. For 3rd party dockpanes, the OperationManager property is null by default. Therefore, the undo/redo buttons on the QAT are usually disabled when a custom dockpane has focus. The user must switch focus back to a dockpane (or pane) that has a valid OperationManager for the undo/redo buttons to "re-enable", assuming there are active undoable and/or redoable operations present.
3rd party developers have 3 choices with regards to OperationManager and custom Dockpanes:
- Do nothing. Leave the OperationManager property null. This is the default.
- Share the OperationManager of the current map (or layout if your dockpane is associated with layout). This is the most common scenario.
- Provide your own OperationManager (not common).
Option 1 has already been explained. A null OperationManager simply means the undo/redo disables when your dockpane is active.
Option 2, by sharing the OperationManager associated with the current map (or layout), the undo/redo stack on the QAT will show the undo/redo operations associated with that map when your dockpane has focus. In practice, assuming all visible dockpanes are sharing the same OperationManager, the QAT undo/redo doesn't change as the user switches focus between the visible dockpanes (including your own). This is usually the desired behavior. To return the OperationManager associated with the current active map add the following code to your dockpane:
//Gets the OperationManager associated with the current map or null
public override OperationManager OperationManager {
get {
return MapView.Active?.Map.OperationManager;
//or LayoutView.Active... for the Layout
}
}
Option 3, if you are implementing your own operations then your dockpane may need to provide its own OperationManager especially if you want your operations to be kept separate from any other operations being performed on the Pro UI. The UndoRedo sample gives an example of implementing custom operations.
Dockpanes have the option of allowing the drop target to be either the entire dockable window or a specific control such as treeview or listview on the dockable window.
To allow dropping data to the entire dockable window, set the DAML attribute isDropTarget to true.
<dockPane id="TOC" caption="Contents" className="DockPanes.TOCContents"
dock="left" isDropTarget="true">
The dockpane’s view model also needs to override the OnDragOver and OnDrop methods of the base ArcGIS.Desktop.Framework.Controls.DockPane class.
By default, the isDropTarget attribute is set to false, meaning the dockpane should specify a UI element in XAML as the drop target. In the example below, the listbox handles drop:
<UserControl x:Class="ArcGIS.Desktop.Mapping.TOC.TOCDockPane"
xmlns:dragDrop="clr-namespace:ArcGIS.Desktop.Framework.DragDrop;assembly=ArcGIS.Desktop.Framework" >
……….
<Style x:Key="bookmarkListBoxStyle" TargetType="{x:Type ListBox}">
<Setter Property="dragDrop:DragDrop.IsDropTarget" Value="True" />
<Setter Property="dragDrop:DragDrop.DropHandler" Value="{Binding}" />
<!-- add these when implementing drag
<Setter Property="dragDrop:DragDrop.IsDragSource" Value="True" />
<Setter Property="dragDrop:DragDrop.DragHandler" Value="{Binding}" />
-->
</Style>
Since the drop handler binds to the dockpane’s view model, the view model needs to override the OnDragOver and OnDrop methods of the base ArcGIS.Desktop.Framework.Controls.DockPane class.
However in some cases, you may want to set the drop handler to a different object other than the dockpane’s view model.
<TreeView x:Name="TOC" Grid.Row="0" ItemsSource="{Binding Maps}"
dragDrop:DragDrop.IsDropTarget="True"
dragDrop:DragDrop.DropHandler="{Binding DropHandler}"
>
</TreeView>
In this case, the "DropHandler" property (referenced in the DropHandler binding) should return an instance of DropHandlerBase, which has OnDragOver and OnDrop methods.
internal class TOCMapViewDropHandler : DropHandlerBase, IDragSource
{
public override void OnDragOver(DropInfo dropInfo)
{
// TODO - add specific code here
}
public override void OnDrop(DropInfo dropData)
{
// TODO - add specific code here
}
// IDragSource
public void StartDrag(DragInfo dragInfo)
{
// TODO - add specific code here
}
}
_tocDropHandler = new TOCMapViewDropHandler(this);
public TOCMapViewDropHandler DropHandler
{
get { return _tocDropHandler; } // Instance of DropHandlerBase
}
Refer to ProConcepts-Framework drag and drop for more information. A sample dock pane implementing both drag and drop is also available: DragAndDrop sample
The Reset Panes command (View > Reset Panes) will reset the application panes to some predefined group. After working in ArcGIS Pro for a long period of time, the application window can become crowded with a wide variety of panes. This new command provides a quick and easy way to close all of the open panes reseting the application to just a predefined group of panes. For example, "Reset Panes for Geoprocessing" closes all open panes, reopening only the Contents, Catalog, and Geoprocessing panes, with Geoprocessing brought to the foreground.
You can reset the Pro application to a predefined group of panes of your choice using DAML. The example DAML snippet below will add a "Reset Pane for Bookmarks" menu item in the "Reset Panes" drop down control on the View tab. When you click the "Reset Panes for Bookmark" menu items, all the currently open dockpanes in Pro will close and the "Manage Bookmarks" pane and the "Contents" pane will be opened. Add this snippet before the <modules>
element.
<DockPaneSets>
<insertDockPaneSet id="esri_DockPaneReset_bookmarks" caption="Reset Panes for Bookmarks">
<DockPaneID refID="esri_mapping_showBookmarksWindow"/>
<DockPaneID refID="esri_core_contentsDockPane"/>
</insertDockPaneSet>
</DockPaneSets>
In the screenshots below, the image on the left shows the default Reset Pane options available in ArcGIS Pro. The image on the right has a new "Reset Panes for Bookmark" option inserted in the Menu items using DAML customization.
ArcGIS Pro provides a standard mechanism to enable contextual help on dockpanes and windows. In the screenshot below you can see two sample implementations of dockpane and window help.
You can implement help for your dockpane by adding the hasHelp="true" attribute to the dockPane tag in DAML and override the OnHelpRequested method of the base ArcGIS.Desktop.Framework.Controls.DockPane class.
Below the hasHelp attribute for the dockPane tag is set to "true":
<dockPanes>
<dockPane id="DockpaneWithHelp_..." hasHelp="true"
caption="..." className="..." dock="..." dockWith="...">
<content className="DockpaneWithHelpView" />
</dockPane>
</dockPanes>
Below is the code-behind implementation to override the OnHelpRequested method of the base ArcGIS.Desktop.Framework.Controls.DockPane class with our desired custom behavior that occurs when the help icon is clicked or the F1 key is pressed. In the sample below the help action simply spawns a browser showing the ArcGIS Pro help page.
internal class DockpaneWithHelpViewModel : DockPane
{
private const string _dockPaneID = "DockpaneWithHelp_...";
protected DockpaneWithHelpViewModel() { }
...
/// <summary>
/// Override the default behavior when the dockpane's help icon is clicked
/// or the F1 key is pressed.
/// </summary>
protected override void OnHelpRequested()
{
System.Diagnostics.Process.Start (@"https://pro.arcgis.com/en/pro-app/help/main");
}
}
The help action is triggered when the operator clicks on the dockpane's help icon or the F1 key is pressed while the dockpane window is the active window.