码迷,mamicode.com
首页 > Windows程序 > 详细

用wpf实现简单的柱状图控件

时间:2016-05-06 19:08:33      阅读:414      评论:0      收藏:0      [点我收藏+]

标签:

 

因为最近的一个项目里需要用到柱状图,找了一些第三方的控件,UI部分定制化不强,很难保证与现有界面的统一。项目当中用到的图形也比较简单,所以干脆自己动手实现。

下面是最终的效果。

技术分享

 

首先讲一下设计思路

  图形控件主要分为四部分:一水平文本,垂直文本,背景线条,以及最主要的柱形部分。

  第一步先绘制背景,因为水平文本和垂直文本都是根据数据源动态计算的,所以内容无法固定。为了方便计算这里以Grid控件为基类,在Grid的基础上进行绘制,因为通过添加Grid的行和列能够很好的控制控件内容的布局。

 

 

1 class WpfChart : Grid
2 {
3 
4 
5 .......
6 
7 
8 }

 

 

 接下来要定义控件的数据源。柱状图的数据源比较简单,可以通过简单的键值对进行设计。为了方便绑定,这里将数据源设计为依赖属性

 

 1 public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable<KeyValuePair<string, double>>), typeof(WpfChart), new PropertyMetadata(new List<KeyValuePair<string,double>>(), OnItemsSourcePropertyChanged));
 2  
 3 public IEnumerable<KeyValuePair<string,double>> ItemsSource
 4 {
 5     get { return (List<KeyValuePair<string, double>>)GetValue(ItemsSourceProperty); }
 6     set { SetValue(ItemsSourceProperty, value); }
 7 }

 

 

为了方便布局,这里将整个控件划分成三个区域,分别用三个Grid控件进行管理这三块区域的内容。

 

1 private readonly Grid _gridTextH = new Grid();
2 private readonly Grid _gridTextV = new Grid();
3 private readonly Grid _gridContent = new Grid();

 

技术分享

 

下面进行垂直、水平内容的添加 ,垂直文本通通放到_gridTextH控件内,水平文本通通放到_gridTextV控件内。

1、通过获取数据源中的最大值,计算控件中需要显示的行数。

2、添加对应的表格线到_gridTextH中。

3、通过获取数据源的长度,添加控件对应的水平文本。

 

 1         void DrawHTextCollection()
 2         {
 3             _gridTextH.ColumnDefinitions.Clear();
 4             _gridTextH.RowDefinitions.Clear();
 5             _gridTextH.Children.Clear();
 6             _gridTextH.Margin = new Thickness(_viewPortPad.Left, 0, 0, 0);
 7             _gridTextH.RowDefinitions.Add(new RowDefinition() {Height = new GridLength(1, GridUnitType.Star)});
 8             _gridTextH.RowDefinitions.Add(new RowDefinition()
 9             {
10                 Height = new GridLength(_viewPortPad.Bottom, GridUnitType.Pixel)
11             });
12 
13             TextBlock tb;
14 
15             foreach (var v in ItemsSource)
16             {
17                 _gridTextH.Children.Add(
18                     tb =
19                         new TextBlock()
20                         {
21                             Text = v.Key,
22                             HorizontalAlignment = HorizontalAlignment.Center,
23                             VerticalAlignment = VerticalAlignment.Top,
24                             Margin = new Thickness(0, 10, 0, 0)
25 
26                         });
27                 _gridTextH.ColumnDefinitions.Add(new ColumnDefinition());
28                 Grid.SetRow(tb, 1);
29                 Grid.SetColumn(tb, _gridTextH.ColumnDefinitions.Count - 1);
30             }
31         }
32 
33 
34 
35 
36        void DrawVTextCollection()
37         {
38             TextBlock tb;
39             Border border;
40             _gridTextV.RowDefinitions.Clear();
41             _gridTextV.Children.Clear();
42             _gridTextV.ColumnDefinitions.Clear();
43             _gridTextV.Margin = new Thickness(0, _viewPortPad.Top, 0, _viewPortPad.Bottom);
44             _gridTextV.ColumnDefinitions.Add(new ColumnDefinition()
45             {
46                 Width = new GridLength(_viewPortPad.Left, GridUnitType.Pixel)
47             });
48             _gridTextV.ColumnDefinitions.Add(new ColumnDefinition()
49             {
50                 Width = new GridLength(1, GridUnitType.Star)
51             });
52             foreach (var v in GetVTextCollection())
53             {
54                 _gridTextV.Children.Add(
55                     tb =
56                         new TextBlock()
57                         {
58                             Text = v.ToString(),
59                             Margin = new Thickness(0, 0, 5, 0),
60                             HorizontalAlignment = HorizontalAlignment.Right,
61                             VerticalAlignment = VerticalAlignment.Bottom
62                         });
63                 _gridTextV.Children.Add(
64                     border =
65                         new Border()
66                         {
67                             BorderBrush = new SolidColorBrush((Color) ColorConverter.ConvertFromString("#FFc0c0c0")),
68                             BorderThickness = new Thickness(0, 0, 0, 1),
69                             VerticalAlignment = VerticalAlignment.Bottom
70                         });
71                 _gridTextV.RowDefinitions.Add(new RowDefinition());
72                 Grid.SetRow(tb, _gridTextV.RowDefinitions.Count - 1);
73                 Grid.SetColumn(border, 1);
74                 Grid.SetRow(border, _gridTextV.RowDefinitions.Count - 1);
75             }
76         }

 

下面是背景生成后的效果图。

 

技术分享

 

最后就是最重要的内容区域了。通通放到_gridContent中。

 

 1 void DrawCoordinate()
 2 {
 3     Rectangle rectangle;
 4     TextBlock tb;
 5     _gridContent.ColumnDefinitions.Clear();
 6     _gridContent.RowDefinitions.Clear();
 7     _gridContent.Children.Clear();
 8 
 9     //_gridContent.Margin = new Thickness(_viewPortPad.Left, 0, 0, _viewPortPad.Bottom);
10     _gridContent.ColumnDefinitions.Add(new ColumnDefinition()
11     {
12         Width = new GridLength(_viewPortPad.Left, GridUnitType.Pixel)
13     });
14     _gridContent.RowDefinitions.Add(new RowDefinition()
15     {
16         Height = new GridLength(1, GridUnitType.Star)
17     });
18     _gridContent.RowDefinitions.Add(new RowDefinition()
19     {
20         Height = new GridLength(_viewPortPad.Bottom, GridUnitType.Pixel)
21     });
22 
23     var maxHeight = _gridContent.ActualHeight - _viewPortPad.Top - _viewPortPad.Bottom;
24     var maxWidth = _gridContent.ActualWidth - _viewPortPad.Left;
25 
26     var list = ItemsSource;
27     foreach (var v in list)
28     {
29         var xx = maxHeight*(v.Value/_chartMaxNumber);
30         _gridContent.Children.Add(
31             rectangle =
32                 new Rectangle()
33                 {
34                     Fill = _defaultBrush,
35                     Height = maxHeight*(v.Value/_chartMaxNumber),
36                     Width = maxWidth/list.Count()*0.6,
37                     VerticalAlignment = VerticalAlignment.Bottom
38                 });
39         var doubleAnimation = new DoubleAnimation(0, maxHeight*(v.Value/_chartMaxNumber),
40             new Duration(new TimeSpan(0, 0, 0, 0, 1000)));
41 
42         rectangle.BeginAnimation(Rectangle.HeightProperty, doubleAnimation);
43 
44         rectangle.Tag = v.Value;
45 
46         if (v.Value == this._maxValue)
47             rectangle.Fill = _maxValueBrush;
48         _gridContent.Children.Add(
49             tb =
50                 new TextBlock()
51                 {
52                     Text = v.Value.ToString("f"),
53                     Margin = new Thickness(0, 0, 0, maxHeight*(v.Value/_chartMaxNumber) + 5),
54                     VerticalAlignment = VerticalAlignment.Bottom,
55                     HorizontalAlignment = HorizontalAlignment.Center,
56 
57                 }
58             );
59 
60 
61         var thicknessAnimation = new ThicknessAnimation(new Thickness(0, 0, 0, 0),
62             new Thickness(0, 0, 0, maxHeight*(v.Value/_chartMaxNumber) + 5),
63             new Duration(new TimeSpan(0, 0, 0, 0, 1000)));
64         tb.BeginAnimation(TextBlock.MarginProperty, thicknessAnimation);
65 
66         rectangle.MouseEnter += Rectangle_MouseEnter;
67         rectangle.MouseLeave += Rectangle_MouseLeave;
68         _gridContent.ColumnDefinitions.Add(new ColumnDefinition());
69         Grid.SetColumn(rectangle, _gridContent.ColumnDefinitions.Count - 1);
70         Grid.SetColumn(tb, _gridContent.ColumnDefinitions.Count - 1);
71     }
72 }

 

 

 

生成的控件功能虽然简单,但定制化很强,任何地方都能修改,摆脱了使用第三方控件的束缚。

 代码位置:http://download.csdn.net/detail/shushukui/9512216

用wpf实现简单的柱状图控件

标签:

原文地址:http://www.cnblogs.com/shushukui/p/5466343.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!