• Aucun résultat trouvé

creating custoM panels

Dans le document professional silverlight (Page 165-169)

As stated earlier in the chapter, the layout system included in Silverlight is not only highly flexible but very extensible. It is quite easy to leverage the layout system to create your own custom layout panels that contain your own unique arrangement logic. In order to show this, this section demon-strates how to create a version of the WrapPanel control shown earlier called SimpleWrapPanel.

The layout logic for the panel will stack its child elements from left to right, starting in the upper-left corner of the panel. When the child elements begin to exceed the width of the panel, the panel will automatically begin to wrap the elements to a new row.

To get started creating a custom panel, simply create a new Silverlight Class Library in your project.

Once the class file has been created, change the class so that it derives from the base Panel object.

This is shown in Listing 5-10.

listing 5-10: Deriving from the base Panel using System;

using System.Windows;

using System.Windows.Controls;

namespace SimpleWrapPanelSample {

public class SimpleWrapPanel : Panel {

} }

Next, you must override two methods from the base PanelMeasureOverride and ArrangeOverride. This is shown in Listing 5-11.

listing 5-11: overriding the Measureoverride and arrangeoverride methods public class SimpleWrapPanel : Panel

{

protected override Size MeasureOverride(Size availableSize) {

}

protected override Size ArrangeOverride(Size finalSize) {

} }

Now all that is left to do is for you to implement your own layout logic in the Measure and Arrange methods. The logic for the SimpleWrapPanel’s MeasureOverride method is shown in Listing 5-12.

listing 5-12: Measureoverride logic for simpleWrapPanel

protected override Size MeasureOverride(Size availableSize) {

Size size = new Size();

foreach (UIElement element in this.Children) {

if (element != null)

{

The first step in the method is to loop through all of the panel’s child elements and call Measure on each one of them, passing in the availableSize parameter. This causes the child elements to calcu-late their own desired sizes.

Next, in the same loop, the Panel control attempts to identify the amount of space needed by the panel for the layout. This is calculated by finding the width of the widest element in the panel and by calculating the sum height of all elements in the panel. Once the size is determined, it is returned as the result of the method. The value returned from this method is the panel’s Desired Size, as dis-cussed earlier in the chapter.

Once the layout system has completed the Measure pass, it then executes its Arrange. The Arrange pass is when the panel actually positions its child elements in the final space allocated to the panel by the layout system. The positioning of the child elements is done by calling the Arrange method on each child of the Panel, passing the child its final desired size and position by using a Rectangle object.

Listing 5-13 shows the panel’s ArrangeOverride method, which includes the positioning logic for the panel.

listing 5-13: arrangeoverride logic for simpleWrapPanel protected override Size ArrangeOverride(Size finalSize)

foreach (UIElement element in this.Children) {

if (element != null) {

left += width;

continues

width = element.DesiredSize.Width;

The logic in the Arrange method for this panel is relatively simple. First, several internal members are defined which help the Panel track information about the positioned elements. The Panel needs to track three things: the cumulative width of all elements it has positioned in the current row, the height of the tallest element in the current row, and the cumulative height of all rows in the panel.

The cumulative width is used to correctly position the next element in the row. The tallest element in the current row is used to determine the overall row height. As each element is positioned, the Panel checks to see if its height is greater than any other element that has been positioned in the row before it. The cumulative row height of all rows in the panel is used to determine the position of the next row.

Next, the method begins to enumerate each child element of the panel, calculating the position for each child element and calling its Arrange method. As the Panel enumerates each element, it sets the Width and Height and X and Y properties of the positioning rectangle using the data from the internal members.

The Panel also checks to determine if the element, when positioned, will exceed the width of the panel. If this is found to be true, the Panel resets the Rectangle’s X and Y properties to reposition the element onto a new row.

listing 5-13 (continued)

Finally, the child elements’ Arrange method is called. A new Rectangle object is created, which is used to provide the panel’s children with the information they need to position themselves within the panel.

Note that in the ArrangeOverride method, if you try to make the height or width of a child element smaller than its desired size, the size passed into the child’s Arrange method is ignored, and the element continues to render at its desired size. If you want to keep the smaller size, then you may need to apply a clip to that element so that it won’t overspill its layout slot. Or earlier during the panel’s Measure phase you can pass in the size that you actually want it to be.

Figure 5-12 shows the results of the panel once it is rendered.

figure 5-12

While the Wrap Panel is a simple example of a custom panel, every panel that you create will follow the same basic Measure and Arrange principles.

Dans le document professional silverlight (Page 165-169)