原来一直以为silverlight里的事件机制也和wpf中的一样或和flex中的一样。但好像并非如此。而是采用了传统的delegate,并不是flex中的事件机制:
以下代码是一个PieChart控件, 当中的事件就是采用delegate
Code
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Windows;
5using System.Windows.Controls;
6using System.Windows.Controls.Primitives;
7using System.Windows.Documents;
8using System.Windows.Input;
9using System.Windows.Media;
10using System.Windows.Markup;
11using System.Windows.Media.Animation;
12using System.Windows.Shapes;
13using System.Collections.ObjectModel;
14
15namespace ZWebClient.UIControls.Charting
16{
17 [ContentProperty("Segments")]
18 public class GPieChart : Canvas
19 {
20 private PieLayoutManager layoutManager;
21
22 public delegate void ClickedDelegate(object sender, RoutedEventArgs e);
23 public event ClickedDelegate PieClicked;
24
25 public void RaisePieClicked(object sender, RoutedEventArgs e)
26 {
27 if (PieClicked != null)
28 PieClicked(sender, e);
29 }
30
31 public GPieChart()
32 {
33 this.layoutManager = new PieLayoutManager(this);
34 this.SizeChanged += delegate { PerformLayout(); };
35
36 this.Segments = new PieSegmentList();
37 this.Segments.CollectionChanged += delegate { PerformLayout(); };
38
39 this.SizeChanged += (ss, ee) =>
40 {
41 layoutManager.LayoutChart();
42 };
43 }
44
45 internal void showDataTip(string tip, Point orig)
46 {
47 if (this.DataTip != null)
48 {
49 //this.DataTip._tip.Width = 100;
50 this.DataTip.ShowDataTip(tip, orig);
51 }
52 }
53
54 internal void hideDataTip()
55 {
56 if (this.DataTip != null)
57 this.DataTip.HideDataTip();
58 }
59
60 private void PerformLayout()
61 {
62 layoutManager.LayoutChart();
63 //layoutManager.PlayAnimation();
64 if (this.DataTip != null)
65 {
66 this.DataTip.HideDataTip();
67 }
68
69 }
70
71 Dependency Properties#region Dependency Properties
72
73 public static readonly DependencyProperty DataTipProperty =
74 DependencyProperty.Register("DataTip", typeof(GDataTip), typeof(GPieChart), new PropertyMetadata(OnDependencyPropertyChanged));
75
76 public static readonly DependencyProperty SegmentsProperty =
77 DependencyProperty.Register("Segments", typeof(PieSegmentList), typeof(GPieChart), new PropertyMetadata(OnDependencyPropertyChanged));
78
79 public static readonly DependencyProperty CenterProperty =
80 DependencyProperty.Register("Center", typeof(Point), typeof(GPieChart), new PropertyMetadata(OnDependencyPropertyChanged));
81
82 public static readonly DependencyProperty RadiusProperty =
83 DependencyProperty.Register("Radius", typeof(double), typeof(GPieChart), new PropertyMetadata(OnDependencyPropertyChanged));
84
85 public static readonly DependencyProperty StrokeProperty =
86 DependencyProperty.Register("Stroke", typeof(Brush), typeof(GPieChart), new PropertyMetadata(OnDependencyPropertyChanged));
87
88 public static readonly DependencyProperty StrokeThicknessProperty =
89 DependencyProperty.Register("StrokeThickness", typeof(double), typeof(GPieChart), new PropertyMetadata(OnDependencyPropertyChanged));
90
91 public static readonly DependencyProperty FontSizeProperty =
92 DependencyProperty.Register("FontSize", typeof(double), typeof(GPieChart), new PropertyMetadata(OnDependencyPropertyChanged));
93
94 private static void OnDependencyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
95 {
96 GPieChart source = d as GPieChart;
97 source.PerformLayout();
98 if (source.DataTip != null)
99 {
100 source.DataTip.HideDataTip();
101 }
102 }
103
104
105 public GDataTip DataTip
106 {
107 get { return (GDataTip)GetValue(DataTipProperty); }
108 set { SetValue(DataTipProperty, value); value.SetActiveCanvas(this); }
109 }
110
111 public PieSegmentList Segments
112 {
113 get { return (PieSegmentList)GetValue(SegmentsProperty); }
114 set { SetValue(SegmentsProperty, value); }
115 }
116
117 public Point Center
118 {
119 get { return (Point)GetValue(CenterProperty); }
120 set { SetValue(CenterProperty, value); }
121 }
122
123 public double Radius
124 {
125 get { return (double)GetValue(RadiusProperty); }
126 set { SetValue(RadiusProperty, value); }
127 }
128
129 public Brush Stroke
130 {
131 get { return (Brush)GetValue(StrokeProperty); }
132 set { SetValue(StrokeProperty, value); }
133 }
134
135 public double StrokeThickness
136 {
137 get { return (double)GetValue(StrokeThicknessProperty); }
138 set { SetValue(StrokeThicknessProperty, value); }
139 }
140
141 public double FontSize
142 {
143 get { return (double)GetValue(FontSizeProperty); }
144 set { SetValue(FontSizeProperty, value); }
145 }
146
147 #endregion
148 }
149
150 public class PieSegment
151 {
152 public PieSegment()
153 {
154 this.HasTransformed = false;
155 this.ShowDataTip = true;
156 this.LittleThan30Degrees = false;
157 }
158
159 public double Percentage
160 {
161 get { return (this.Degrees / 360.0) * 100.0; }
162 set { this.Degrees = 360.0 * (value / 100.0); }
163 }
164 public double Degrees { get; set; }
165 public Brush Foreground { get; set; }
166 public Brush HighlightForeground { get; set; }
167 public Brush DataLabelForeground { get; set; }
168 public int DataLabelFontSize { get; set; }
169 public FontWeight DataLabelFontWeight { get; set; }
170 public string DataLabel { get; set; }
171 public bool ShowDataLabel { get; set; }
172 public bool ShowDataTip { get; set; }
173 public string DataTipString { get; set; }
174 public bool HasTransformed { get; set; }
175 public bool LittleThan30Degrees { get; set; }
176 public BiPieChart ParentChart { get; set; }
177 public bool IsMultiPieChartSegment { get; set; }
178 }
179
180 public class PieSegmentList : ObservableCollection<PieSegment>
181 {
182 public double TotalDegrees
183 {
184 get { return this.Sum(x => x.Degrees); }
185 }
186 }
187
188 internal class PieLayoutManager
189 {
190 private GPieChart pieChart;
191
192 internal PieLayoutManager(GPieChart targetPieChart)
193 {
194
195 if (targetPieChart == null)
196 {
197 throw new ArgumentNullException("targetPieChart");
198 }
199
200 this.pieChart = targetPieChart;
201 }
202
203 private double radius; private Point center;
204
205 internal bool setDefaults()
206 {
207 bool result = true;
208
209 if (double.IsNaN(this.pieChart.ActualHeight))
210 return false;
211
212 if (this.pieChart.ActualHeight <= 0)
213 return false;
214
215 if (double.IsNaN(this.pieChart.ActualWidth))
216 return false;
217
218 if (this.pieChart.ActualWidth <= 0)
219 return false;
220
221 double minSize = (this.pieChart.ActualWidth > this.pieChart.ActualHeight) ? this.pieChart.ActualHeight : this.pieChart.ActualWidth;
222
223 this.center = new Point(this.pieChart.ActualWidth / 2, this.pieChart.ActualHeight / 2);
224 this.radius = minSize / 2;
225
226 return result;
227
228 }
229
230 internal void LayoutChart()
231 {
232 if (Math.Abs(this.pieChart.Segments.TotalDegrees) > 360)
233 {
234 throw new InvalidOperationException("Total Degrees for PieChart cannot be greater than 360° or less than -360°");
235 }
236
237 if (!setDefaults())
238 return;
239
240 this.pieChart.Children.Clear();
241
242 double startAngle = 0.0;
243
244 LabelLocations = new List<string>();
245
246 foreach (PieSegment segment in this.pieChart.Segments)
247 {
248 double endAngle = startAngle + segment.Degrees;
249
250 LayoutSegment(startAngle, endAngle, segment);
251
252 startAngle = endAngle;
253
254 }
255
256 }
257
258 List<string> LabelLocations;
259
260 private void LayoutSegment(double startAngle, double endAngle, PieSegment segment)
261 {
262 startAngle = startAngle > 360 ? 360 : startAngle;
263 endAngle = endAngle > 360 ? 360 : endAngle;
264 TextBlock dataLabel = new TextBlock(); // for data label
265 dataLabel.Tag = segment.DataLabel;
266 dataLabel.IsHitTestVisible = false;
267 dataLabel.Text = segment.DataLabel;
268 dataLabel.FontSize = segment.DataLabelFontSize;
269 dataLabel.Foreground = segment.DataLabelForeground;
270 dataLabel.FontWeight = segment.DataLabelFontWeight;
271
272 double distinct = segment.ShowDataTip == true ? 0 : 4;
273 if (startAngle == 0 && endAngle == 360)
274 {
275 // draw the whole ellipse
276 this.pieChart.Children.Clear();
277 Ellipse e = new Ellipse();
278 e.Width = (this.radius - distinct) * 2;
279 e.Height = (this.radius - distinct) * 2;
280 e.Stroke = this.pieChart.Stroke;
281 e.StrokeThickness = this.pieChart.StrokeThickness;
282 e.Fill = segment.Foreground;
283
284 this.pieChart.Children.Add(e);
285 Canvas.SetLeft(e, this.center.X - this.radius + distinct);
286 Canvas.SetTop(e, this.center.Y - this.radius + distinct);
287 this.pieChart.Children.Add(dataLabel);
288 Canvas.SetLeft(dataLabel, this.radius - distinct);
289 Canvas.SetTop(dataLabel, this.radius - distinct);
290
291 if (segment.ShowDataTip)
292 {
293 if (!segment.IsMultiPieChartSegment && segment.ParentChart.Name != "piePndMsg")
294 {
295 e.Cursor = Cursors.Hand;
296 }
297 e.MouseEnter += delegate
298 {
299 e.Fill = segment.HighlightForeground;
300 Point p = new Point(this.center.X, this.center.Y);
301 this.pieChart.showDataTip(segment.DataTipString, p);
302 };
303 e.MouseLeave += delegate
304 {
305 e.Fill = segment.Foreground;
306 this.pieChart.hideDataTip();
307 };
308 e.MouseLeftButtonDown += delegate
309 {
310 this.pieChart.RaisePieClicked(segment, new RoutedEventArgs() { });
311 };
312 }
313 return;
314 }
315 else if (startAngle == 360 && endAngle == 360)
316 {
317 return;
318 }
319
320 double newX = 0;
321 double newY = 0;
322 double prevDegree = startAngle;
323 double angle = segment.Degrees;
324
325 newX = this.center.X + (this.radius - distinct) * Math.Sin((prevDegree + angle) * Math.PI / 180);
326 newY = this.center.Y - (this.radius - distinct) * Math.Cos((prevDegree + angle) * Math.PI / 180);
327
328 Path path = new Path();
329
330 Brush pathStroke = this.pieChart.Stroke;
331 Brush pieFill = segment.Foreground;
332 path.Stroke = pathStroke;
333 path.StrokeThickness = this.pieChart.StrokeThickness;
334 path.Fill = pieFill;
335 PathGeometry geo = new PathGeometry();
336
337 PathFigureCollection figures = new PathFigureCollection();
338 PathFigure figure = new PathFigure();
339
340 PathSegmentCollection lines = new PathSegmentCollection();
341 LineSegment line = new LineSegment();
342
343 figure.StartPoint = this.center;
344
345 Point startP = GetCircumferencePoint(startAngle, this.radius - distinct);
346
347 line.Point = startP;
348 lines.Add(line);
349
350 ArcSegment activePie = new ArcSegment();
351
352 if (angle >= 180)
353 activePie.IsLargeArc = true;
354 else
355 activePie.IsLargeArc = false;
356
357 Point endPoint = new Point(newX, newY);
358 activePie.Point = endPoint;
359
360 activePie.Size = new Size(this.radius - distinct, this.radius - distinct);
361 activePie.SweepDirection = SweepDirection.Clockwise;
362
363 lines.Add(activePie);
364
365 line = new LineSegment();
366 line.Point = this.center;
367 lines.Add(line);
368
369 figure.Segments = lines;
370 figures.Add(figure);
371 geo.Figures = figures;
372 path.Data = geo;
373
374 if (!segment.IsMultiPieChartSegment && segment.ParentChart.Name != "piePndMsg" && segment.ShowDataTip == true)
375 {
376 path.Cursor = Cursors.Hand;
377 }
378
379 mouse event#region mouse event
380 path.MouseLeftButtonDown += delegate
381 {
382 //if (segment.HasTransformed)
383 //{
384 // path.RenderTransform = null;
385 // dataLabel.RenderTransform = null;
386 // segment.HasTransformed = false;
387 //}
388 //else
389 //{
390 // TranslateTransform tt = new TranslateTransform();
391 // Point transBy = GetCircumferencePoint((startAngle + endAngle) / 2.0, 20.0);
392 // Point translate = new Point(transBy.X - this.center.X, transBy.Y - this.center.Y);
393
394 // tt.X = translate.X; tt.Y = translate.Y;
395 // path.RenderTransform = tt;
396 // dataLabel.RenderTransform = tt;
397
398 // segment.HasTransformed = true;
399 //}
400 if (segment.ShowDataTip)
401 {
402 this.pieChart.RaisePieClicked(segment, new RoutedEventArgs() { });
403 }
404
405 };
406 //path.MouseLeftButtonUp += delegate
407 //{
408 // if (!segment.IsMultiPieChartSegment && segment.ShowDataTip)
409 // {
410 // this.pieChart.RaisePieClicked(segment, new RoutedEventArgs() { });
411 // }
412 //};
413
414 path.MouseEnter += (dd,ee)=>
415 {
416 path.Fill = segment.HighlightForeground;
417
418
419 double sFactor = segment.Degrees / 2.1;
420 double tX = this.center.X + this.radius * 0.5 * Math.Sin((endAngle - sFactor) * Math.PI / 180);
421 double tY = this.center.Y - this.radius * 0.5 * Math.Cos((endAngle - sFactor) * Math.PI / 180);
422
423
424
425 Point orig = new Point(tX, tY);
426
427 if (path.RenderTransform != null)
428 {
429 TranslateTransform tt = path.RenderTransform as TranslateTransform;
430 if (tt != null)
431 {
432 orig = tt.Transform(orig);
433 }
434 }
435
436 if (segment.ShowDataTip)
437 this.pieChart.showDataTip(segment.DataTipString, orig);
438 };
439
440 path.MouseLeave += delegate
441 {
442 path.Fill = segment.Foreground;
443 this.pieChart.hideDataTip();
444 };
445 #endregion
446
447 this.pieChart.Children.Add(path);
448 if (segment.ShowDataLabel)
449 {
450 double labelAngle = (segment.LittleThan30Degrees == true ? 40 : segment.Percentage * 3.60) / 2.1;
451 double dX = -12;
452 double dY = -5;
453 double sF = 0.58;
454
455 newX = this.center.X + this.radius * sF * Math.Sin((startAngle + labelAngle) * Math.PI / 180) + dX;
456 newY = this.center.Y - this.radius * sF * Math.Cos((startAngle + labelAngle) * Math.PI / 180) + dY;
457
458 path.Tag = segment.DataLabel;
459 this.pieChart.Children.Add(dataLabel);
460 Canvas.SetLeft(dataLabel, newX);
461 Canvas.SetTop(dataLabel, newY);
462
463 }
464
465 }
466
467 //private Point GetCircumferencePoint(double angle, double radius)
468 //{
469 // return GetCircumferencePoint(angle, radius);
470
471 //}
472
473 private Point GetCircumferencePoint(double angle, double radius)
474 {
475 double angleRad = (Math.PI / 180.0) * angle;
476
477 double x = this.center.X + radius * Math.Sin(angleRad);
478 double y = this.center.Y - radius * Math.Cos(angleRad);
479
480 return new Point(x, y);
481 }
482 }
483}
484
485
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Windows;
5using System.Windows.Controls;
6using System.Windows.Controls.Primitives;
7using System.Windows.Documents;
8using System.Windows.Input;
9using System.Windows.Media;
10using System.Windows.Markup;
11using System.Windows.Media.Animation;
12using System.Windows.Shapes;
13using System.Collections.ObjectModel;
14
15namespace ZWebClient.UIControls.Charting
16{
17 [ContentProperty("Segments")]
18 public class GPieChart : Canvas
19 {
20 private PieLayoutManager layoutManager;
21
22 public delegate void ClickedDelegate(object sender, RoutedEventArgs e);
23 public event ClickedDelegate PieClicked;
24
25 public void RaisePieClicked(object sender, RoutedEventArgs e)
26 {
27 if (PieClicked != null)
28 PieClicked(sender, e);
29 }
30
31 public GPieChart()
32 {
33 this.layoutManager = new PieLayoutManager(this);
34 this.SizeChanged += delegate { PerformLayout(); };
35
36 this.Segments = new PieSegmentList();
37 this.Segments.CollectionChanged += delegate { PerformLayout(); };
38
39 this.SizeChanged += (ss, ee) =>
40 {
41 layoutManager.LayoutChart();
42 };
43 }
44
45 internal void showDataTip(string tip, Point orig)
46 {
47 if (this.DataTip != null)
48 {
49 //this.DataTip._tip.Width = 100;
50 this.DataTip.ShowDataTip(tip, orig);
51 }
52 }
53
54 internal void hideDataTip()
55 {
56 if (this.DataTip != null)
57 this.DataTip.HideDataTip();
58 }
59
60 private void PerformLayout()
61 {
62 layoutManager.LayoutChart();
63 //layoutManager.PlayAnimation();
64 if (this.DataTip != null)
65 {
66 this.DataTip.HideDataTip();
67 }
68
69 }
70
71 Dependency Properties#region Dependency Properties
72
73 public static readonly DependencyProperty DataTipProperty =
74 DependencyProperty.Register("DataTip", typeof(GDataTip), typeof(GPieChart), new PropertyMetadata(OnDependencyPropertyChanged));
75
76 public static readonly DependencyProperty SegmentsProperty =
77 DependencyProperty.Register("Segments", typeof(PieSegmentList), typeof(GPieChart), new PropertyMetadata(OnDependencyPropertyChanged));
78
79 public static readonly DependencyProperty CenterProperty =
80 DependencyProperty.Register("Center", typeof(Point), typeof(GPieChart), new PropertyMetadata(OnDependencyPropertyChanged));
81
82 public static readonly DependencyProperty RadiusProperty =
83 DependencyProperty.Register("Radius", typeof(double), typeof(GPieChart), new PropertyMetadata(OnDependencyPropertyChanged));
84
85 public static readonly DependencyProperty StrokeProperty =
86 DependencyProperty.Register("Stroke", typeof(Brush), typeof(GPieChart), new PropertyMetadata(OnDependencyPropertyChanged));
87
88 public static readonly DependencyProperty StrokeThicknessProperty =
89 DependencyProperty.Register("StrokeThickness", typeof(double), typeof(GPieChart), new PropertyMetadata(OnDependencyPropertyChanged));
90
91 public static readonly DependencyProperty FontSizeProperty =
92 DependencyProperty.Register("FontSize", typeof(double), typeof(GPieChart), new PropertyMetadata(OnDependencyPropertyChanged));
93
94 private static void OnDependencyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
95 {
96 GPieChart source = d as GPieChart;
97 source.PerformLayout();
98 if (source.DataTip != null)
99 {
100 source.DataTip.HideDataTip();
101 }
102 }
103
104
105 public GDataTip DataTip
106 {
107 get { return (GDataTip)GetValue(DataTipProperty); }
108 set { SetValue(DataTipProperty, value); value.SetActiveCanvas(this); }
109 }
110
111 public PieSegmentList Segments
112 {
113 get { return (PieSegmentList)GetValue(SegmentsProperty); }
114 set { SetValue(SegmentsProperty, value); }
115 }
116
117 public Point Center
118 {
119 get { return (Point)GetValue(CenterProperty); }
120 set { SetValue(CenterProperty, value); }
121 }
122
123 public double Radius
124 {
125 get { return (double)GetValue(RadiusProperty); }
126 set { SetValue(RadiusProperty, value); }
127 }
128
129 public Brush Stroke
130 {
131 get { return (Brush)GetValue(StrokeProperty); }
132 set { SetValue(StrokeProperty, value); }
133 }
134
135 public double StrokeThickness
136 {
137 get { return (double)GetValue(StrokeThicknessProperty); }
138 set { SetValue(StrokeThicknessProperty, value); }
139 }
140
141 public double FontSize
142 {
143 get { return (double)GetValue(FontSizeProperty); }
144 set { SetValue(FontSizeProperty, value); }
145 }
146
147 #endregion
148 }
149
150 public class PieSegment
151 {
152 public PieSegment()
153 {
154 this.HasTransformed = false;
155 this.ShowDataTip = true;
156 this.LittleThan30Degrees = false;
157 }
158
159 public double Percentage
160 {
161 get { return (this.Degrees / 360.0) * 100.0; }
162 set { this.Degrees = 360.0 * (value / 100.0); }
163 }
164 public double Degrees { get; set; }
165 public Brush Foreground { get; set; }
166 public Brush HighlightForeground { get; set; }
167 public Brush DataLabelForeground { get; set; }
168 public int DataLabelFontSize { get; set; }
169 public FontWeight DataLabelFontWeight { get; set; }
170 public string DataLabel { get; set; }
171 public bool ShowDataLabel { get; set; }
172 public bool ShowDataTip { get; set; }
173 public string DataTipString { get; set; }
174 public bool HasTransformed { get; set; }
175 public bool LittleThan30Degrees { get; set; }
176 public BiPieChart ParentChart { get; set; }
177 public bool IsMultiPieChartSegment { get; set; }
178 }
179
180 public class PieSegmentList : ObservableCollection<PieSegment>
181 {
182 public double TotalDegrees
183 {
184 get { return this.Sum(x => x.Degrees); }
185 }
186 }
187
188 internal class PieLayoutManager
189 {
190 private GPieChart pieChart;
191
192 internal PieLayoutManager(GPieChart targetPieChart)
193 {
194
195 if (targetPieChart == null)
196 {
197 throw new ArgumentNullException("targetPieChart");
198 }
199
200 this.pieChart = targetPieChart;
201 }
202
203 private double radius; private Point center;
204
205 internal bool setDefaults()
206 {
207 bool result = true;
208
209 if (double.IsNaN(this.pieChart.ActualHeight))
210 return false;
211
212 if (this.pieChart.ActualHeight <= 0)
213 return false;
214
215 if (double.IsNaN(this.pieChart.ActualWidth))
216 return false;
217
218 if (this.pieChart.ActualWidth <= 0)
219 return false;
220
221 double minSize = (this.pieChart.ActualWidth > this.pieChart.ActualHeight) ? this.pieChart.ActualHeight : this.pieChart.ActualWidth;
222
223 this.center = new Point(this.pieChart.ActualWidth / 2, this.pieChart.ActualHeight / 2);
224 this.radius = minSize / 2;
225
226 return result;
227
228 }
229
230 internal void LayoutChart()
231 {
232 if (Math.Abs(this.pieChart.Segments.TotalDegrees) > 360)
233 {
234 throw new InvalidOperationException("Total Degrees for PieChart cannot be greater than 360° or less than -360°");
235 }
236
237 if (!setDefaults())
238 return;
239
240 this.pieChart.Children.Clear();
241
242 double startAngle = 0.0;
243
244 LabelLocations = new List<string>();
245
246 foreach (PieSegment segment in this.pieChart.Segments)
247 {
248 double endAngle = startAngle + segment.Degrees;
249
250 LayoutSegment(startAngle, endAngle, segment);
251
252 startAngle = endAngle;
253
254 }
255
256 }
257
258 List<string> LabelLocations;
259
260 private void LayoutSegment(double startAngle, double endAngle, PieSegment segment)
261 {
262 startAngle = startAngle > 360 ? 360 : startAngle;
263 endAngle = endAngle > 360 ? 360 : endAngle;
264 TextBlock dataLabel = new TextBlock(); // for data label
265 dataLabel.Tag = segment.DataLabel;
266 dataLabel.IsHitTestVisible = false;
267 dataLabel.Text = segment.DataLabel;
268 dataLabel.FontSize = segment.DataLabelFontSize;
269 dataLabel.Foreground = segment.DataLabelForeground;
270 dataLabel.FontWeight = segment.DataLabelFontWeight;
271
272 double distinct = segment.ShowDataTip == true ? 0 : 4;
273 if (startAngle == 0 && endAngle == 360)
274 {
275 // draw the whole ellipse
276 this.pieChart.Children.Clear();
277 Ellipse e = new Ellipse();
278 e.Width = (this.radius - distinct) * 2;
279 e.Height = (this.radius - distinct) * 2;
280 e.Stroke = this.pieChart.Stroke;
281 e.StrokeThickness = this.pieChart.StrokeThickness;
282 e.Fill = segment.Foreground;
283
284 this.pieChart.Children.Add(e);
285 Canvas.SetLeft(e, this.center.X - this.radius + distinct);
286 Canvas.SetTop(e, this.center.Y - this.radius + distinct);
287 this.pieChart.Children.Add(dataLabel);
288 Canvas.SetLeft(dataLabel, this.radius - distinct);
289 Canvas.SetTop(dataLabel, this.radius - distinct);
290
291 if (segment.ShowDataTip)
292 {
293 if (!segment.IsMultiPieChartSegment && segment.ParentChart.Name != "piePndMsg")
294 {
295 e.Cursor = Cursors.Hand;
296 }
297 e.MouseEnter += delegate
298 {
299 e.Fill = segment.HighlightForeground;
300 Point p = new Point(this.center.X, this.center.Y);
301 this.pieChart.showDataTip(segment.DataTipString, p);
302 };
303 e.MouseLeave += delegate
304 {
305 e.Fill = segment.Foreground;
306 this.pieChart.hideDataTip();
307 };
308 e.MouseLeftButtonDown += delegate
309 {
310 this.pieChart.RaisePieClicked(segment, new RoutedEventArgs() { });
311 };
312 }
313 return;
314 }
315 else if (startAngle == 360 && endAngle == 360)
316 {
317 return;
318 }
319
320 double newX = 0;
321 double newY = 0;
322 double prevDegree = startAngle;
323 double angle = segment.Degrees;
324
325 newX = this.center.X + (this.radius - distinct) * Math.Sin((prevDegree + angle) * Math.PI / 180);
326 newY = this.center.Y - (this.radius - distinct) * Math.Cos((prevDegree + angle) * Math.PI / 180);
327
328 Path path = new Path();
329
330 Brush pathStroke = this.pieChart.Stroke;
331 Brush pieFill = segment.Foreground;
332 path.Stroke = pathStroke;
333 path.StrokeThickness = this.pieChart.StrokeThickness;
334 path.Fill = pieFill;
335 PathGeometry geo = new PathGeometry();
336
337 PathFigureCollection figures = new PathFigureCollection();
338 PathFigure figure = new PathFigure();
339
340 PathSegmentCollection lines = new PathSegmentCollection();
341 LineSegment line = new LineSegment();
342
343 figure.StartPoint = this.center;
344
345 Point startP = GetCircumferencePoint(startAngle, this.radius - distinct);
346
347 line.Point = startP;
348 lines.Add(line);
349
350 ArcSegment activePie = new ArcSegment();
351
352 if (angle >= 180)
353 activePie.IsLargeArc = true;
354 else
355 activePie.IsLargeArc = false;
356
357 Point endPoint = new Point(newX, newY);
358 activePie.Point = endPoint;
359
360 activePie.Size = new Size(this.radius - distinct, this.radius - distinct);
361 activePie.SweepDirection = SweepDirection.Clockwise;
362
363 lines.Add(activePie);
364
365 line = new LineSegment();
366 line.Point = this.center;
367 lines.Add(line);
368
369 figure.Segments = lines;
370 figures.Add(figure);
371 geo.Figures = figures;
372 path.Data = geo;
373
374 if (!segment.IsMultiPieChartSegment && segment.ParentChart.Name != "piePndMsg" && segment.ShowDataTip == true)
375 {
376 path.Cursor = Cursors.Hand;
377 }
378
379 mouse event#region mouse event
380 path.MouseLeftButtonDown += delegate
381 {
382 //if (segment.HasTransformed)
383 //{
384 // path.RenderTransform = null;
385 // dataLabel.RenderTransform = null;
386 // segment.HasTransformed = false;
387 //}
388 //else
389 //{
390 // TranslateTransform tt = new TranslateTransform();
391 // Point transBy = GetCircumferencePoint((startAngle + endAngle) / 2.0, 20.0);
392 // Point translate = new Point(transBy.X - this.center.X, transBy.Y - this.center.Y);
393
394 // tt.X = translate.X; tt.Y = translate.Y;
395 // path.RenderTransform = tt;
396 // dataLabel.RenderTransform = tt;
397
398 // segment.HasTransformed = true;
399 //}
400 if (segment.ShowDataTip)
401 {
402 this.pieChart.RaisePieClicked(segment, new RoutedEventArgs() { });
403 }
404
405 };
406 //path.MouseLeftButtonUp += delegate
407 //{
408 // if (!segment.IsMultiPieChartSegment && segment.ShowDataTip)
409 // {
410 // this.pieChart.RaisePieClicked(segment, new RoutedEventArgs() { });
411 // }
412 //};
413
414 path.MouseEnter += (dd,ee)=>
415 {
416 path.Fill = segment.HighlightForeground;
417
418
419 double sFactor = segment.Degrees / 2.1;
420 double tX = this.center.X + this.radius * 0.5 * Math.Sin((endAngle - sFactor) * Math.PI / 180);
421 double tY = this.center.Y - this.radius * 0.5 * Math.Cos((endAngle - sFactor) * Math.PI / 180);
422
423
424
425 Point orig = new Point(tX, tY);
426
427 if (path.RenderTransform != null)
428 {
429 TranslateTransform tt = path.RenderTransform as TranslateTransform;
430 if (tt != null)
431 {
432 orig = tt.Transform(orig);
433 }
434 }
435
436 if (segment.ShowDataTip)
437 this.pieChart.showDataTip(segment.DataTipString, orig);
438 };
439
440 path.MouseLeave += delegate
441 {
442 path.Fill = segment.Foreground;
443 this.pieChart.hideDataTip();
444 };
445 #endregion
446
447 this.pieChart.Children.Add(path);
448 if (segment.ShowDataLabel)
449 {
450 double labelAngle = (segment.LittleThan30Degrees == true ? 40 : segment.Percentage * 3.60) / 2.1;
451 double dX = -12;
452 double dY = -5;
453 double sF = 0.58;
454
455 newX = this.center.X + this.radius * sF * Math.Sin((startAngle + labelAngle) * Math.PI / 180) + dX;
456 newY = this.center.Y - this.radius * sF * Math.Cos((startAngle + labelAngle) * Math.PI / 180) + dY;
457
458 path.Tag = segment.DataLabel;
459 this.pieChart.Children.Add(dataLabel);
460 Canvas.SetLeft(dataLabel, newX);
461 Canvas.SetTop(dataLabel, newY);
462
463 }
464
465 }
466
467 //private Point GetCircumferencePoint(double angle, double radius)
468 //{
469 // return GetCircumferencePoint(angle, radius);
470
471 //}
472
473 private Point GetCircumferencePoint(double angle, double radius)
474 {
475 double angleRad = (Math.PI / 180.0) * angle;
476
477 double x = this.center.X + radius * Math.Sin(angleRad);
478 double y = this.center.Y - radius * Math.Cos(angleRad);
479
480 return new Point(x, y);
481 }
482 }
483}
484
485