zoukankan      html  css  js  c++  java
  • 用wpf实现简单的柱状图控件

    因为最近的一个项目里需要用到柱状图,找了一些第三方的控件,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

  • 相关阅读:
    blender+threejs
    170112、solr从服务器配置整合到项目实战
    170111、MapperScannerConfigurer处理过程源码分析
    170110、Spring 事物机制总结
    170109、JSONP是什么
    170106、用9种办法解决 JS 闭包经典面试题之 for 循环取 i
    170105、MySQL 性能优化的最佳 20+ 条经验
    170104、js内置对象与原生对象
    170103、Redis官方集群方案 Redis Cluster
    161230、利用代理中间件实现大规模Redis集群
  • 原文地址:https://www.cnblogs.com/shushukui/p/5466343.html
Copyright © 2011-2022 走看看