Sometimes when using a Docking control and implementing complex UI with it we need to add some custom rules about allowing some panes to be docked in some parts of the application and to disallow them to dock to other parts. As this behavior is quite complex itself, we’ve decided to enable some scenarios to be available in XAML in a declarative way (the more static scenarios) and some scenarios to be available only through the code-behind.
In this post I will guide you through some simple steps that will show you how you could use both approaches. First of all I will explain you some of the properties of the Compass class that will allow to control its options. After that I will show how to statically set the enabled compass directions. At the end I will show you how to implement some complex logic for enabling and disabling compass directions.
Both the Compass and RootCompass controls have some dependency properties that allow you to customize their docking directions. The RootCompass inherits from the Compass class, so it contains all the properties defined for the Compass class. Both classes have the following properties:
These properties by default are controlling the visibility of the Compass and RootCompass parts. On Figure 1.1 and 1.2 you can see the parts of the Compass and the RootCompass controls.
Figure 1.1 Parts of the Compass Control
Figure 1.2 Parts of the RootCompass Control
In the RootCompass class the IsCenterIndicatorVisible property is not in use, because the RootCompass doesn’t have a center indicator. Figure 2.1 and 2.2 shows how each property affects both of the compasses:
Figure 2.1 Compass indicator visibility properties
Figure 2.2 RootCompass indicator visibility properties
One common scenario is to say that the user is not allowed to dock at one side of the Docking control (for example at the right one). Another common scenario is that our application doesn’t allow the user to have more than one pane in a group. Both of these scenarios are pretty static and we could achieve them using the previously mentioned configuration properties of the Compass and RootCompass controls without writing any code-behind. To achieve the first scenario we need to say to the RootCompass that its right indicator is always invisible. You could do that using the RootCompassStyle property of the Docking control. Listing 1.1 shows how we could use this property.
Listing 1.1: Configure RootCompass using the RootCompassStyle property of the Docking control
When is needed for a group of the same type panes, or even for each pane, to be granted different permissions for docking, the code-behind is used for achieving this more complex scenario.
First, you must hook on the PreviewShowCompass event of the Docking control in the XAML and implement your logic in the event-handler in the code-behind. To divide the logic for the RootCompass and the other Compass you should use the TargetGroup property of the e argument. If its TargetGroup property is null, this means that the event is fired for the RootCompass, if not – for the other Compass. It is good to keep in mind that the programming overrides the styles in XAML, so if you are using both approaches the explicit settings of the properties are “stronger”.
So let’s create an example that will utilize the features we already mentioned.
First, we need to create a method called GetPaneType, which returns the type of the panes. This is achieved by comparing the resources of the panes, more specificly the color of the brush of the pane’s background, using simple if statements. We will need the type of the panes, so that we can decide which Compass indicators to show and which to hide depending on these types. Here is the code:
PaneType GetPaneType(RadPane pane)
Panel c = pane.Content
Then, we will define a method called CanDockIn. The return type of this method is Boolean and its parameters are:
The return value will indicate whether the first pane (paneToDock) can be docked next to the second one(paneInTargetGroup). The third parameter indicates where we want to dock the first pane relatively to second one - to its left, right, top or bottom side or in the same group. We will use this value to set the visibility of the indicators of the Compass for each pane in the event PreviewShowCompass. For that we make 2 variables paneInTargetGroupType, of type PaneType, which is the pane that is the targeted one (the one that we are holding and moving at the moment), and paneToDockType, also of type PaneType, which is the one in which we are eventually going to dock. To the variable paneToDockType is assigned the value of GetPaneType(paneToDock) - this is the method that we have initially created with the first argument of the method CanDockIn. To the paneInTargetGroupType is assigned the GetPaneType(paneInTargetGroup).
After getting the type of the panes via the method GetPaneType, using switch statements we set the value (true or false) for each type of pane (in the example olive, purple and blue). The value of the outer switch expression, which is shown below, is the paneToDockType. If we take for example this code snippet:
position != DockPosition.Left && position != DockPosition.Right;
This code shows that one olive pane:
In a similar way is defined the visibility of the indicators for the other remaining pane groups.
Similar logic is used for defining the visibility of the indicators of the RootCompass in the method CanDock. Again switch statements are used to define for each pane which indicators of the RootCompass are enabled.
position != DockPosition.Left;
Here we can see that for the olive pane the docking to the left is disabled, for the blue pane all 4 indicators in the RootCompass are disabled and for the purple pane all indicators are visible.
We are now able to set the visibility of all indicators of the two Compasses for every pane in the PreviewShowCompass event.
The values for the previously mentioned properties IsLeftIndicatorVisible, IsTopIndicatorVisible, IsRightIndicatorVisible, IsBottomIndicatorVisible, IsCenterIndicatorVisible are determined with the help of the methods CanDockIn and CanDock, which we have created.
sender, Telerik.Windows.Controls.Docking.PreviewShowCompassEventArgs e)
e.Compass.IsCenterIndicatorVisible = CanDockIn(e.DraggedSplitContainer, e.TargetGroup, DockPosition.Center);
e.Compass.IsLeftIndicatorVisible = CanDockIn(e.DraggedSplitContainer, e.TargetGroup, DockPosition.Left);
e.Compass.IsTopIndicatorVisible = CanDockIn(e.DraggedSplitContainer, e.TargetGroup, DockPosition.Top);
e.Compass.IsRightIndicatorVisible = CanDockIn(e.DraggedSplitContainer, e.TargetGroup, DockPosition.Right);
e.Compass.IsBottomIndicatorVisible = CanDockIn(e.DraggedSplitContainer, e.TargetGroup, DockPosition.Bottom);
e.Compass.IsLeftIndicatorVisible = CanDock(e.DraggedSplitContainer, DockPosition.Left);
e.Compass.IsTopIndicatorVisible = CanDock(e.DraggedSplitContainer, DockPosition.Top);
e.Compass.IsRightIndicatorVisible = CanDock(e.DraggedSplitContainer, DockPosition.Right);
e.Compass.IsBottomIndicatorVisible = CanDock(e.DraggedSplitContainer, DockPosition.Bottom);
e.Canceled = !(CompassNeedsToShow(e.Compass));
As we can see in the Boolean value, which is returned by the methods CanDock and CanDockIn, is set to the corresponding properties IsCenterIndicatorVisible, IsLeftIndicatorVisible, IsTopIndicatorVisible, IsRightIndicatorVisible, IsBottomIndicatorVisible, which make the indicator visible or invisible.
The property Canceled of the e argument, if set to true, disables the whole Compass. The line
e.Canceled = !(CompassNeedsToShow(e.Compass));
refers to another method, called CompassNeedsToShow, which checks if all indicators are disabled, if so, disables the whole Compass, like so:
compass.IsLeftIndicatorVisible || compass.IsTopIndicatorVisible || compass.IsRightIndicatorVisible || compass.IsBottomIndicatorVisible || compass.IsCenterIndicatorVisible;
Here you can find an example which illustrates the described implementation of the RadDocking Control. For more information please refer to Telerik’s online demos for Silverlight, the demos for WPF and help documentation for WPF and help documentation for Silverlight.