WPF Custom Control (1) -- dashboard design [1], wpf dashboard

Source: Internet
Author: User

WPF Custom Control (1) -- dashboard design [1], wpf dashboard

0. speak nonsense

I took over a new project and went back to PC development. There are many control libraries on the Internet, and there are also a lot of dashboard (gauge) functions, but I personally think the library is very bloated, and I plan to write a control library by myself, one is for learning, and the other is for projects. The following is what I spent the afternoon doing. Let's take a look at the results first:

This dial is still ugly at present, and will be improved step by step later, including various beautification, I believe I can do it, come on !! This is my first blog. I will continue to write and try my best to express every technical detail. Source Code address: http://files.cnblogs.com/files/endlesscoding/Gauge.zip

1. Dial Overall Design

A dial should consist of four parts: the dial contour, the scale (including a small scale and a large scale), the scale value, and the pointer. In the process of creation, it is easy to use a little mathematical knowledge, as long as you think carefully. The following knowledge points are used in the design process. Of course, it also includes some basic knowledge of C # And WPF. If you have any questions, you can refer to the introduction to WPF by Liu tiemeng.

Dial outer contour Scale Scale value Pointer
Path plotting Straight Line TextBlock Control Path plotting

2. Dial Contour

Preliminary design, the outer contour consists of three sections: yellow, green, red, with the help of WPF powerful drawing function, made a gradient, slightly beautify, such. (The radius of this circle is 200px)

Obviously, this circle is composed of three arcs. If you observe carefully, you can see two white lines vaguely, that is, the demarcation of the three arcs.

1. Draw a yellow arc

The Code is as follows:

 1 <Path StrokeThickness="30" Width="420" Height="400" StrokeStartLineCap="Round"> 2     <Path.Data> 3         <PathGeometry Figures="M 0,200 A 200,200 0 0 1 58.57864,58.57864"/> 4     </Path.Data> 5     <Path.Stroke> 6         <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> 7             <LinearGradientBrush.GradientStops> 8                 <GradientStop Offset="0" Color="Green"/> 9                 <GradientStop Offset="1.0" Color="Yellow"/>10             </LinearGradientBrush.GradientStops>11         </LinearGradientBrush>12     </Path.Stroke>13 </Path>

The most critical code is the 3rd lines. The following table describes the data points. If you have any questions, write them down first and use them later.

M 0,200 A 200,200 0 0 1 58.57864, 58.57864

M is the start mark of the Path drawing.

The starting coordinate of the arc is (0,200)

A (arc) is an arc mark.

(200,200) indicates the X axis radius: 200; Y axis radius: 200

Arc rotation angle [0] (with a starting point and an ending point, I personally feel that this value is useless)

Mark of the dominant arc [0] (no, the arc angle is less than 180)

Positive and negative angle mark [1] (circle clockwise)

Indicates the end point, calculated using a mathematical formula

(58.57864, 58.57864) is calculated as follows:

The angle of the yellow arc is 1/4*180 = 45 degrees. The Coordinate Calculation of the yellow point is as follows.

2. Draw green and red Arcs

With the above yellow arc painting as the basis, green and red are the same principle, the following code is directly given to draw three arc

 1 <Path Stroke="Yellow" StrokeThickness="30" Width="420" Height="400" StrokeStartLineCap="Round"> 2     <Path.Data> 3         <PathGeometry Figures="M 0,200 A 200,200 0 0 1 58.57864,58.57864"/> 4     </Path.Data> 5 </Path> 6 <Path Stroke="Green" StrokeThickness="30" Width="420" Height="400"> 7     <Path.Data> 8         <PathGeometry Figures="M 58.57864,58.57864 A 200,200 0 0 1 341.42136,58.57864" /> 9     </Path.Data>10 </Path>11 <Path Stroke="Red" StrokeThickness="30" Width="420" Height="400" StrokeEndLineCap="Round">12     <Path.Data>13         <PathGeometry Figures="M 341.42136,58.57864 A 200,200 0 0 1 400,200" />14     </Path.Data>15 </Path>

The focus of the Code is on the bold numeric part. To ensure the code is concise and the structure is clear, the gradient processing is removed, followed. The effects of the above Code are as follows:


3. Dial scale drawing

The dial scale is composed of many straight line segments and can also be drawn in XAML. But in this way, the Code volume is a little large, and we also need to manually enter many coordinate values. The method is very stupid and we have not played the C # power at all. Below I will first use the XAML language to write a scale (Small Scale) to illustrate the principle, and then use the C # language to draw all the scales in the background, so as to facilitate the maintenance of code and the customization of the dashboard. Shows how to calculate the two coordinates of the linear scale at the 20-degree angle. The starting point of a linear scale is on a circle with a center (200,200) and a radius of 180. The ending point is on a circle with a center (200,200) and a radius of 170.

Based on the above calculation results, the code and Effect of writing a straight line XAML language are as follows:

<Line Stroke="Green" StrokeThickness="2" X1="30.85533" Y1="138.43637" X2="40.25225" Y2="141.85658"/>

1. Draw a small scale

With the basic knowledge above, all the small scales can be easily drawn. first look at the C # background code:

1 public MainWindow () 2 {3 InitializeComponent (); 4 this. drawScale (); 5} 6 /// <summary> 7 // draw the dial scale 8 /// </summary> 9 private void DrawScale () 10 {11 for (int I = 0; I <= 180; I + = 5) 12 {13 // Add the dial Line 14 Line lineScale = new Line (); 15 16 lineScale. stroke = new SolidColorBrush (Color. fromRgb (0xFF, 0x00, 0); // use the red line 17 lineScale. strokeThickness = 1; // The line width is 118 // the starting point of the linear scale. Note that the angle is converted to the radian value of 19.LineScale. X1 = 200-170 * Math. Cos (I * Math. PI/180 );20LineScale. Y1 = 200-170 * Math. Sin (I * Math. PI/180 );21 // the end point of the linear scale. Note that the angle is converted to 22 in radians.LineScale. X2 = 200-180 * Math. Cos (I * Math. PI/180 );23LineScale. Y2 = 200-180 * Math. Sin (I * Math. PI/180 );24 // draw a straight line on the Canvas 25 this. gaugeCanvas. Children. Add (lineScale); 26} 27}

Similarly, the key points of the Code are in rows 19,20, 180, 170-= 10. This 10 represents the length of a small scale. After all the scales are drawn, the effect is as follows:

2. draw large scales

A large scale occurs once every five small scales with a length of 20 PX. With the foundation of drawing a small scale, it is very easy to implement the scale. You only need to slightly modify the DrawScale function, as shown in the bold code below:

1 private void DrawScale () 2 {3 for (int I = 0; I <= 180; I ++ = 5) 4 {5 // Add the dial Line 6 Line lineScale = new Line (); 7 8If (I % 25 = 0) // It indicates that five small scales have been drawn and a large scale has been added.9{10LineScale. X1 = 200-160 * Math. Cos (I * Math. PI/180 );11LineScale. Y1 = 200-160 * Math. Sin (I * Math. PI/180 );12LineScale. Stroke = new SolidColorBrush (Color. FromRgb (0x00, 0xFF, 0 ));13LineScale. StrokeThickness = 3;14} 15 else16 {17 lineScale. x1 = 200-170 * Math. cos (I * Math. PI/180); 18 lineScale. y1 = 200-170 * Math. sin (I * Math. PI/180); 19 lineScale. stroke = new SolidColorBrush (Color. fromRgb (0xFF, 0x00, 0); 20 lineScale. strokeThickness = 1; 21} 22 // the end point of the linear scale. Note that the angle is converted to 23 lineScale in radians. x2 = 200-180 * Math. cos (I * Math. PI/180); 24 lineScale. y2 = 200-180 * Math. sin (I * Math. PI/180); 25 // draw a straight line on the Canvas 26 this. gaugeCanvas. children. add (lineScale); 27} 28}

Shows the final implementation effect, which is getting closer and closer.

4. Add dial scale value

The scale value is represented by a text block (TextBlock control ). It is easy to implement the coordinates of the text block in the dial. Note that the starting point of the coordinates of all controls is zero in the upper left corner, when the angle is greater than 90 degrees, the coordinates should be compensated. It may not be clear. In the code, the DrawScale () function is modified as follows:

1 private void DrawScale () 2 {3 for (int I = 0; I <= 180; I ++ = 5) 4 {5 // Add the dial Line 6 Line lineScale = new Line (); 7 8 if (I % 25 = 0) 9 {10 lineScale. x1 = 200-160 * Math. cos (I * Math. PI/180); 11 lineScale. y1 = 200-160 * Math. sin (I * Math. PI/180); 12 lineScale. stroke = new SolidColorBrush (Color. fromRgb (0x00, 0xFF, 0); 13 lineScale. strokeThickness = 3; 14 15 // Add the scale value 16 TextBlock txtScale = new TextBlock (); 17 txtScale. text = (I ). toString (); 18 txtScale. fontSize = 10; 19 if (I <= 90) // you can modify the cursor value by 20 {21 Canvas. setLeft (txtScale, 200-155 * Math. cos (I * Math. PI/180); 22} 23 else24 {25 Canvas. setLeft (txtScale, 190-155 * Math. cos (I * Math. PI/180); 26} 27 Canvas. setTop (txtScale, 200-155 * Math. sin (I * Math. PI/180); 28 this. gaugeCanvas. children. add (txtScale); 29} 30 else31 {32 lineScale. x1 = 200-170 * Math. cos (I * Math. PI/180); 33 lineScale. y1 = 200-170 * Math. sin (I * Math. PI/180); 34 lineScale. stroke = new SolidColorBrush (Color. fromRgb (0xFF, 0x00, 0); 35 lineScale. strokeThickness = 1; 36} 37 38 lineScale. x2 = 200-180 * Math. cos (I * Math. PI/180); 39 lineScale. y2 = 200-180 * Math. sin (I * Math. PI/180); 40 41 this. gaugeCanvas. children. add (lineScale); 42} 43}

The effect after the scale value is added is as follows:

5. pointer Rendering

There are many ways to make the dial pointer. Many people on the Internet say that they should use images instead, but once the images are enlarged, they will become blurred. Therefore, I should do it myself, A simple pointer is also implemented using the Path method and Path plotting. The XAML code is as follows. The pointer is mainly composed of two straight lines and an arc, and is filled with orange.

 1 <Path x:Name="indicatorPin" Fill="Orange"> 2     <Path.Data> 3         <PathGeometry> 4             <PathGeometry.Figures> 5                 <PathFigure StartPoint="200,195" IsClosed="True"> 6                     <PathFigure.Segments> 7                         <LineSegment Point="20,200"/> 8                         <LineSegment Point="200,205"/> 9                     </PathFigure.Segments>10                 </PathFigure>11             </PathGeometry.Figures>12         </PathGeometry>13     </Path.Data>14 </Path>

There is an indicator value in the middle of many dials. Here, I also use a text block to copy it. The XAML language is as follows. Note that the position of the text block should be properly allocated.

<TextBlock x:Name="currentValueTxtBlock" FontSize="20" Canvas.Left="140" Canvas.Top="150"/>

Shows the final appearance:

6. Turn the pointer

It is obvious that the rotation of the pointer is centered on (200,200) and angles. RotateTransform and DoubleAnimation are used to implement the rotation animation. The animation duration is allocated according to the angle size. The animation duration is 1 degree and 8 milliseconds. Currently, the rotation angle is randomly generated. Here, I write the rotation animation in the canvas_MouseDown event. C # The Code is as follows:

 1 private void Canvas_MouseDown(object sender, MouseButtonEventArgs e) 2 { 3     RotateTransform rt = new RotateTransform(); 4     rt.CenterX = 200; 5     rt.CenterY = 200; 6  7     this.indicatorPin.RenderTransform = rt; 8  9     angelCurrent = angleNext;10     Random random = new Random();11     angleNext = random.Next(180);12 13     double timeAnimation = Math.Abs(angelCurrent - angleNext) * 8;14     DoubleAnimation da = new DoubleAnimation(angelCurrent, angleNext, new Duration(TimeSpan.FromMilliseconds(timeAnimation)));15     da.AccelerationRatio = 1;16     rt.BeginAnimation(RotateTransform.AngleProperty, da);

The final result is as follows. I finally finished it and enjoyed it !!


This dial is very simple at present, but it is made by yourself step by step. If you need to add more powerful customization functions, I believe it is handy. The first time I wrote a blog, it was much harder to express than I imagined. At the same time, in order to better express the effect, I used the visio drawing, MathType Public Editor, recording window video using screen recording software, and then took a look at the gif with thunder, finally, it is not easy to process the gif image and publish it to the blog. I believe it will become easier in the future.

At the same time, the next target beautifies and encapsulates the dial into user controls for project calls.

Next, create a chart control. Stay tuned !!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.