3.2 Custom Layout rules
The previous section describes the Windows Phone System layout Panel and layout system related principles, then the system layout Panel does not necessarily meet all the layout rules you want to implement, if there are some special layout rules, the System layout panel is not supported, this time need to customize the implementation of a layout panel, Encapsulates the logic of layout rules in a custom layout panel. Then our section starts with a practical need to implement a custom-defined layout panel. The layout law we want to implement in this section is to arrange the sub-elements in the layout panel according to the arrangement rules of the circle, let's take a look at the detailed implementation of this example.
3.2.1 Creating a Layout class
The first thing to do in a Windows Phone panel that implements a custom layout rule like grid and StackPanel is to create a custom layout class. All layout panels need to derive from the Panel class and customize the process of implementing their measurements and permutations. The Children property in the Panel class represents a sub-object within the layout panel, which requires that all sub-objects in the panel be obtained according to the Children property, and then measured and arranged according to the relevant rules.
If our layout class needs to pass in some special parameters outside, then we need to implement the related properties in the Layout class. Of course, like heigh, width and so on these panel class originally supported properties we need not to define, as we in this example to achieve the circular layout, this time is required a circular radius size, the size of this radius can be used as a property to let the value of the outside to pass in, The layout class then handles the measurement and arrangement of the child objects based on the size of the radius. It is important to note that when the custom RADIUS attribute changes, the Invalidatearrange method needs to be called to re-trigger the layout of the arrangement, otherwise the radius will not play any role.
Code Listing 3-2 : Custom layout Rules (source code: Chapter 3rd \examples_3_2)
Let's take a look at the custom Circlepanel class:
650) this.width=650; "alt=" Copy Code "src=" Http://common.cnblogs.com/images/copycode.gif "/>
public class CirclePanel : Panel { //a custom RADIUS variable private double _radius = 0; public Circlepanel () { } //Register Radius dependency property //" Radius represents the name of the Radius property // typeof (Double) represents the type of RADIUS property // typeof (Circlepanel) represents the attribution type of the RADIUS attribute // new propertymetadata (0.0, onradiuspropertychanged)) The metadata instance that represents the RADIUS attribute, 0.0 is the default value, and Onradiuspropertychanged is the event of the property change Public static readonly dependencyproperty radiusproperty = dependencyproperty.registerattached ("Radius", typeof (Double), typeof (Circlepanel), new propertymetadata (0.0, onradiuspropertychanged)); // Define RADIUS Properties public double Radius { get { return (Double) GetValue (Radiusproperty); } set { setvalue (Radiusproperty, value); } } //Implementing Radius Property Change Events private Static void onradiuspropertychanged (dependencyobject obj, Dependencypropertychangedeventargs e) { //gets the Circlepanel object that triggered the property change CirclePanel target = (Circlepanel) obj; //gets the latest value passed in and assigns a value to the RADIUS variable target._radius = (Double) e.newvalue; //the permutation state, rearranging target. Invalidatearrange (); } //overloads of the base classMeasureOverride Methods protected override Size MeasureOverride (size availablesize) { //logic for processing measurement sub-objects return availablesize; } //Arrangeoverride methods for overloaded base classes protected override size arrangeoverride (size finalsize) { // Handling logical return finalSize; of arranging sub-objects } }
650) this.width=650; "alt=" Copy Code "src=" Http://common.cnblogs.com/images/copycode.gif "/>
3.2.2 Realization of measurement process
The process of measurement is implemented on overloaded MeasureOverride methods, and the first thing that needs to be done on the MeasureOverride method is to traverse all the sub-objects once, calling its measure method to measure the size of the sub-object. Then in the measurement process can get to the sub-object measurement of the width of the height, we can according to this information to customize the panel to allocate its size.
650) this.width=650; "alt=" Copy Code "src=" Http://common.cnblogs.com/images/copycode.gif "/>
protected override size measureoverride (Size availableSize) { //the maximum width of the variable double maxelementwidth = 0; // Traverse all sub-objects and call the measure method of the sub-object to measure, take out the maximum width of the sub-object foreach ( Uielement child in children) { //measuring sub-objects child. Measure (availablesize); maxelementwidth = math.max (child. Desiredsize.width, maxelementwidth); } //the size of the two radius and the maximum width of twice times the most panel width &nbSp; double panelwidth = 2 * this. radius + 2 * maxelementwidth; // The minimum value of the panel's assigned height width and calculated width is the actual size of the faceplate double width = math.min (panelwidth, availablesize.width); double heigh = math.min (panelwidth, availablesize.height); return new size (Width, heigh); }
650) this.width=650; "alt=" Copy Code "src=" Http://common.cnblogs.com/images/copycode.gif "/>
3.2.3 Implementing the arrangement process
The process of arranging is implemented on the overloaded Arrangeoverride method, and the object is arranged by the relevant rules on the Arrangeoverride method one by one. What we want to achieve in the example is that the object is arranged in a fixed circle, so the Arrangeoverride method needs to calculate the angular size of each sub-object, calculate the coordinates of the sub-object in the panel by the angle, and then rotate the child object to fit the circular layout by a certain angle. The permutation principle is shown in Figure 3.7, and the implementation code is as follows.
650) this.width=650; "src=" Http://images.cnitblog.com/i/152755/201406/021344117553651.png "/>
650) this.width=650; "alt=" Copy Code "src=" Http://common.cnblogs.com/images/copycode.gif "/>
protected override size arrangeoverride (Size finalSize) { //current angle, starting from 0 double degree = 0; // Calculate the angle size occupied by each sub-object double degreeStep = (double) 360 / this. children.count; //Calculation double mx = this. desiredsize.width / 2; double my = This. desiredsize.height / 2; //Traverse all sub-objects to arrange foreach (Uielement child in children) { //Convert angle to Radian unit double angle = math.pi * degree / 180.0; //calculates the coordinate value of x, Y on the arc based on radians double x = math.cos (angle) * this._radius; double y = math.sin (angle) * this._radius; //Use the transform effect to make the control rotate the angle degree rotatetransform rotatetransform = new rotatetransform (); rotateTransform.Angle = degree; rotatetransform.centerx = 0; rotatetransform.centery = 0; Child. rendertransform = rotatetransform; //arranges sub-object child. Arrange (New rect (mx + x, my + y, child. Desiredsize.width, child. desiredsize.height)) //angle increment degree += degreeStep; } return finalSize; }
650) this.width=650; "alt=" Copy Code "src=" Http://common.cnblogs.com/images/copycode.gif "/>
3.2.4 Applying layout rules
We've implemented the custom circular layout control above, and now we're going to apply the layout Panel on the XAML page to lay it out. In this example, we also use a slider control to dynamically change the size of the layout panel's radius to see how the layout changes.
First we introduce the space in the XAML page where the layout panel is located, as follows:
Xmlns:local= "Clr-namespace:custompaneldemo"
The custom circular layout control is then applied on the XAML page, and the radius of the circular layout control is dynamically assigned by the valuechanged of the slider control. The code is as follows:
650) this.width=650; "alt=" Copy Code "src=" Http://common.cnblogs.com/images/copycode.gif "/>
MainPage.xaml File Main code------------------------------------------------------------------------------------------------------ ------------ <grid x:name= "Contentpanel" grid.row= "1" margin= " 12,0,12,0 "> <Grid.RowDefinitions> <rowdefinition height= "Auto"/> <rowdefinition height= "Auto"/> </Grid.RowDefinitions> <slider grid.row= "0" value= "5" valuechanged= "Slider_valuechanged_1" ></ Slider> <local:circlepanel x:name= "CirclePanel" radius= " grid.row=" 1 " horizontalalignment=" center " verticalalignment=" center " > <textblock>start here</textblock> <textblock>textblock 1</textblock > <textblock>textblock 2 </TextBlock> <TextBlock> textblock 3</textblock> < textblock>textblock 4</textblock> <TextBlock>TextBlock 5</TextBlock> <TextBlock>TextBlock 6</TextBlock> <TextBlock>TextBlock 7</TextBlock> &nBsp;</local:circlepanel> </grid>
650) this.width=650; "alt=" Copy Code "src=" Http://common.cnblogs.com/images/copycode.gif "/>
650) this.width=650; "alt=" Copy Code "src=" Http://common.cnblogs.com/images/copycode.gif "/>
MainPage.xaml.cs File Main code--------------------------------------------------------------------------------------------------- ---------------private void Slider_valuechanged_1 (object sender, Rangebasevaluechangedeventargs e) {if (Cir Clepanel = null) {Circlepanel.radius = E.newvalue * 10; } }
650) this.width=650; "alt=" Copy Code "src=" Http://common.cnblogs.com/images/copycode.gif "/>
650) this.width=650; "src=" Http://images.cnitblog.com/i/152755/201406/021347547705486.png "/>
This article comes from the deep understanding of Windows Phone 8.1 UI Control programming
Source code Download: Http://vdisk.weibo.com/s/zt_pyrfNHoezI
Welcome to follow my Weibo @wp forestry administration
WP8.1 Technology Group: 372552293
[Wp8.1ui Control Programming] Windows Phone Custom layout rules