WPF 自定義柱狀圖 BarChart

来源:http://www.cnblogs.com/kybs0/archive/2016/09/03/5836036.html
-Advertisement-
Play Games

WPF 自定義柱狀圖 當前的Telerik控制項、DevExpress控制項在圖表控制項方面做得不錯,但是有時項目中需要特定的樣式,不是只通過修改圖表的模板和樣式就能實現的。 或者說,通過修改當前的第三方控制項以達到項目中UI的界面效果,花費的時間遠比重新自定義一個控制項要長得多! 所以直接自定義柱狀圖吧~下 ...


WPF 自定義柱狀圖 

當前的Telerik控制項、DevExpress控制項在圖表控制項方面做得不錯,但是有時項目中需要特定的樣式,不是只通過修改圖表的模板和樣式就能實現的。

或者說,通過修改當前的第三方控制項以達到項目中UI的界面效果,花費的時間遠比重新自定義一個控制項要長得多!

所以直接自定義柱狀圖吧~下麵是柱狀圖的效果:

1、新建一個UserControl,在界面上添加一些簡單的佈局

<UserControl x:Class="WpfApplication11.BarChartControl"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
            mc:Ignorable="d" 
            d:DesignHeight="100" d:DesignWidth="200" Loaded="BarChartControl_OnLoaded">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid x:Name="HeaderGrid" Grid.Row="0" Grid.Column="1" Height="20">
        </Grid>

        <Grid x:Name="LeftGrid" Grid.Row="1" Grid.Column="0">
        </Grid>
        <Border x:Name="MainBorder" Grid.Row="1" Grid.Column="1" BorderThickness="2,0,2,0" BorderBrush="Black">
        </Border>
        <Grid x:Name="MainGridForRow1" Grid.Row="1" Grid.Column="1">

        </Grid>
        <Grid x:Name="MainGridFrom0To1" Grid.Row="0" Grid.Column="1" Grid.RowSpan="2">

        </Grid>
        <Grid x:Name="RightGrid" Grid.Row="1" Grid.Column="2">
        </Grid>

        <Grid x:Name="BottomGrid" Grid.Row="2" Grid.Column="1">
        </Grid>
    </Grid>
</UserControl>
View Code

2、UserControl的後臺界面

通過添加一些依賴屬性,然後在後臺生成界面。也可以把柱狀替換成RadioButton,實現柱狀圖選擇,添加選擇事件的委托方法。

 /// <summary>
    /// BarChartControl.xaml 的交互邏輯
    /// </summary>
    public partial class BarChartControl : UserControl
    {
        public BarChartControl()
        {
            InitializeComponent();
        }

        public Brush BorderBrush
        {
            get { return (Brush)GetValue(BorderBrushProperty); }
            set { SetValue(BorderBrushProperty, value); }
        }

        public static readonly DependencyProperty BorderBrushProperty = DependencyProperty.Register("BorderBrush",
        typeof(Brush), typeof(BarChartControl),
        new PropertyMetadata(Brushes.Black));

        public Thickness BorderThickness
        {
            get { return (Thickness)GetValue(BorderThicknessProperty); }
            set { SetValue(BorderThicknessProperty, value); }
        }

        public static readonly DependencyProperty BorderThicknessProperty = DependencyProperty.Register("BorderThickness",
        typeof(Thickness), typeof(BarChartControl),
        new PropertyMetadata(new Thickness(1.0, 0.0, 1.0, 1.0)));

        public AxisYModel AxisY
        {
            get { return (AxisYModel)GetValue(AxisYProperty); }
            set { SetValue(AxisYProperty, value); }
        }

        public static readonly DependencyProperty AxisYProperty = DependencyProperty.Register("AxisY",
        typeof(AxisYModel), typeof(BarChartControl),
        new PropertyMetadata(new AxisYModel()));

        public AxisXModel AxisX
        {
            get { return (AxisXModel)GetValue(AxisXProperty); }
            set { SetValue(AxisXProperty, value); }
        }

        public static readonly DependencyProperty AxisXProperty = DependencyProperty.Register("AxisX",
        typeof(AxisXModel), typeof(BarChartControl),
        new PropertyMetadata(new AxisXModel()));
        public double HeaderHeight
        {
            get { return (double)GetValue(HeaderHeightProperty); }
            set { SetValue(HeaderHeightProperty, value); }
        }
        public static readonly DependencyProperty HeaderHeightProperty = DependencyProperty.Register("HeaderHeight",
        typeof(double), typeof(BarChartControl), new PropertyMetadata(10.0));
        public string Header
        {
            get { return (string)GetValue(HeaderProperty); }
            set { SetValue(HeaderProperty, value); }
        }
        public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register("Header",
        typeof(string), typeof(BarChartControl), new PropertyMetadata());

        private void BarChartControl_OnLoaded(object sender, RoutedEventArgs e)
        {
            MainBorder.BorderBrush = BorderBrush;
            MainBorder.BorderThickness = BorderThickness;

            BottomGrid.Height = AxisX.Height;
            LeftGrid.Width = AxisY.Width;

            SetYTitlesContent();

            SetXDatasContent();
        }

        private void SetXDatasContent()
        {
            var axisXModel = AxisX;
            if (axisXModel.Datas.Count > 0)
            {
                int count = axisXModel.Datas.Count;
                for (int i = 0; i < count + 1; i++)
                {
                    BottomGrid.ColumnDefinitions.Add(new ColumnDefinition());
                    MainGridFrom0To1.ColumnDefinitions.Add(new ColumnDefinition());
                }
                int index = 0;
                foreach (var data in axisXModel.Datas)
                {
                    //底部
                    var textblock = new TextBlock();
                    textblock.Text = data.Name;
                    textblock.Foreground = axisXModel.ForeGround;
                    textblock.VerticalAlignment = VerticalAlignment.Top;
                    textblock.TextAlignment = TextAlignment.Center;
                    textblock.HorizontalAlignment = HorizontalAlignment.Right;
                    double textBlockWidth = data.LabelWidth;
                    textblock.Width = data.LabelWidth;
                    textblock.Margin = new Thickness(0, 5, -textBlockWidth / 2, 0);
                    Grid.SetColumn(textblock, index);
                    BottomGrid.Children.Add(textblock);


                    //主內容
                    var stackPanel = new StackPanel();
                    stackPanel.Orientation = Orientation.Vertical;

                    var tbl = new TextBlock();
                    tbl.Height = 15;
                    tbl.Margin = new Thickness(0, 0, 0, 5);
                    tbl.Text = data.Value.ToString();
                    tbl.Foreground = axisXModel.ForeGround;
                    tbl.HorizontalAlignment = HorizontalAlignment.Center;
                    stackPanel.Children.Add(tbl);

                    var rectangle = new Rectangle();
                    rectangle.Width = data.BarWidth;
                    double maxValue = AxisY.Titles.Max(i => i.Value);
                    rectangle.Height = (data.Value / maxValue) * (this.ActualHeight - BottomGrid.Height - HeaderHeight);
                    var linearBrush = new LinearGradientBrush()
                    {
                        StartPoint = new Point(1, 0),
                        EndPoint = new Point(1, 1),
                        GradientStops = new GradientStopCollection() { 
                            new GradientStop()
                            {
                                Color = data.FillBrush, Offset = 0
                            }, new GradientStop()
                            {
                                Color = data.FillEndBrush, Offset = 1
                            }
                        }
                    };
                    rectangle.Fill = linearBrush;
                    rectangle.HorizontalAlignment = HorizontalAlignment.Center;

                    stackPanel.Children.Add(rectangle);
                    stackPanel.Margin = new Thickness(0, 0, -textBlockWidth / 2, 0);
                    stackPanel.VerticalAlignment = VerticalAlignment.Bottom;
                    stackPanel.HorizontalAlignment = HorizontalAlignment.Right;
                    Grid.SetColumn(stackPanel, index);
                    MainGridFrom0To1.Children.Add(stackPanel);
                    index++;
                }
            }
        }

        private void SetYTitlesContent()
        {
            var axisYModel = AxisY;
            if (axisYModel.Titles.Count > 0)
            {
                int gridRows = axisYModel.Titles.Count - 1;
                for (int i = 0; i < gridRows; i++)
                {
                    LeftGrid.RowDefinitions.Add(new RowDefinition());
                    MainGridForRow1.RowDefinitions.Add(new RowDefinition());
                }
                int index = 0;
                foreach (var title in axisYModel.Titles)
                {
                    var textblock = new TextBlock();
                    textblock.Text = title.Name;
                    textblock.Foreground = axisYModel.ForeGround;
                    textblock.HorizontalAlignment = HorizontalAlignment.Right;
                    textblock.Height = title.LabelHeight;
                    if (index < gridRows)
                    {
                        textblock.VerticalAlignment = VerticalAlignment.Bottom;
                        textblock.Margin = new Thickness(0, 0, 5, -title.LabelHeight / 2);//因為設置在行底部還不夠,必須往下移
                        Grid.SetRow(textblock, gridRows - index - 1);
                    }
                    else
                    {
                        textblock.VerticalAlignment = VerticalAlignment.Top;
                        textblock.Margin = new Thickness(0, -title.LabelHeight / 2, 5, 0);//最後一個,設置在頂部
                        Grid.SetRow(textblock, 0);
                    }
                    LeftGrid.Children.Add(textblock);

                    var border = new Border();
                    border.Height = title.LineHeight;
                    border.BorderBrush = title.LineBrush;
                    double thickness = Convert.ToDouble(title.LineHeight) / 2;
                    border.BorderThickness = new Thickness(0, thickness, 0, thickness);
                    if (index < gridRows)
                    {
                        border.VerticalAlignment = VerticalAlignment.Bottom;
                        border.Margin = new Thickness(0, 0, 0, -thickness);//因為設置在行底部還不夠,必須往下移
                        Grid.SetRow(border, gridRows - index - 1);
                    }
                    else
                    {
                        border.VerticalAlignment = VerticalAlignment.Top;
                        border.Margin = new Thickness(0, -thickness, 0, 0);//最後一個,設置在頂部
                        Grid.SetRow(border, 0);
                    }
                    Grid.SetColumn(border, 0);
                    Grid.SetColumnSpan(border, AxisX.Datas.Count + 1);
                    MainGridForRow1.Children.Add(border);
                    index++;
                }
            }
        }
        /// <summary>
        /// 設置分行
        /// </summary>
        /// <param name="leftGrid"></param>
        /// <param name="count"></param>
        private void SetGridRowDefinitions(Grid leftGrid, int count)
        {
            for (int i = 0; i < count; i++)
            {
                leftGrid.RowDefinitions.Add(new RowDefinition());
            }
        }
    }
    public class AxisXModel
    {
        private double _height = 20;
        /// <summary>
        /// 高度
        /// </summary>
        public double Height
        {
            get
            {
                return _height;
            }
            set { _height = value; }
        }

        private Brush _foreGround = Brushes.Black;
        /// <summary>
        /// 字體顏色
        /// </summary>
        public Brush ForeGround
        {
            get { return _foreGround; }
            set { _foreGround = value; }
        }

        List<AxisXDataModel> _datas = new List<AxisXDataModel>();
        /// <summary>
        /// 數據
        /// </summary>
        public List<AxisXDataModel> Datas
        {
            get { return _datas; }
            set { _datas = value; }
        }
    }
    public class AxisYModel
    {
        private double _width = 20;
        /// <summary>
        /// 寬度
        /// </summary>
        public double Width { get { return _width; } set { _width = value; } }

        private Brush _foreGround = Brushes.Black;
        /// <summary>
        /// 字體顏色
        /// </summary>
        public Brush ForeGround { get { return _foreGround; } set { _foreGround = value; } }

        List<AxisYDataModel> _titles = new List<AxisYDataModel>();
        /// <summary>
        /// 左側標題列表
        /// </summary>
        public List<AxisYDataModel> Titles
        {
            get { return _titles; }
            set { _titles = value; }
        }
    }
    public class AxisXDataModel : DataModel
    {
        private double _labelWidth = 20;
        /// <summary>
        /// 底部標簽-單個寬度
        /// </summary>
        public double LabelWidth
        {
            get { return _labelWidth; }
            set { _labelWidth = value; }
        }
        private double _barWidth = 20;
        /// <summary>
        /// Bar寬度
        /// </summary>
        public double BarWidth
        {
            get { return _barWidth; }
            set { _barWidth = value; }
        }

        private Color _fillBrush = Colors.Blue;
        /// <summary>
        /// Bar填充顏色
        /// </summary>
        public Color FillBrush
        {
            get
            {
                return _fillBrush;
            }
            set { _fillBrush = value; }
        }

        private Color _fillEndBrush = Colors.Blue;

        public Color FillEndBrush
        {
            get
            {
                return _fillEndBrush;
            }
            set { _fillEndBrush = value; }
        }
    }
    public class AxisYDataModel : DataModel
    {
        private double _labelHeight = 15;
        /// <summary>
        /// 左側標題欄-單個標題高度
        /// </summary>
        public double LabelHeight
        {
            get { return _labelHeight; }
            set { _labelHeight = value; }
        }
        private double _lineHeight = 0.2;
        /// <summary>
        /// GridLine高度
        /// </summary>
        public double LineHeight
        {
            get { return _lineHeight; }
            set { _lineHeight = value; }
        }

        private Brush _lineBrush = Brushes.Blue;
        /// <summary>
        /// Bar填充顏色
        /// </summary>
        public Brush LineBrush
        {
            get { return _lineBrush; }
            set { _lineBrush = value; }
        }
    }
    public class DataModel
    {
        /// <summary>
        /// 顯示名稱
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 值
        /// </summary>
        public double Value { get; set; }
    }
View Code

3、主界面引用

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wpfApplication11="clr-namespace:WpfApplication11"
        x:Class="WpfApplication11.MainWindow"
        Title="MainWindow" Height="350" Width="600" Background="#FF7CADBD">
    <Grid>
        <wpfApplication11:BarChartControl BorderBrush="White" Width="500" Height="250" BorderThickness="2,0,2,0" HeaderHeight="20">
            <wpfApplication11:BarChartControl.AxisY>
                <wpfApplication11:AxisYModel Width="30" ForeGround="White">
                    <wpfApplication11:AxisYModel.Titles>
                        <wpfApplication11:AxisYDataModel Name="0" Value="0"></wpfApplication11:AxisYDataModel>
                        <wpfApplication11:AxisYDataModel Name="20" Value="20"></wpfApplication11:AxisYDataModel>
                        <wpfApplication11:AxisYDataModel Name="40" Value="40"></wpfApplication11:AxisYDataModel>
                        <wpfApplication11:AxisYDataModel Name="60" Value="60"></wpfApplication11:AxisYDataModel>
                        <wpfApplication11:AxisYDataModel Name="80" Value="80"></wpfApplication11:AxisYDataModel>
                        <wpfApplication11:AxisYDataModel Name="100" Value="100"></wpfApplication11:AxisYDataModel>
                    </wpfApplication11:AxisYModel.Titles>
                </wpfApplication11:AxisYModel>
            </wpfApplication11:BarChartControl.AxisY>
            <wpfApplication11:BarChartControl.AxisX>
                <wpfApplication11:AxisXModel Height="30" ForeGround="White">
                    <wpfApplication11:AxisXModel.Datas>
                        <wpfApplication11:AxisXDataModel Name="A" Value="100" FillBrush="DeepSkyBlue" FillEndBrush="#FF6CD7FB"></wpfApplication11:AxisXDataModel>
                        <wpfApplication11:AxisXDataModel Name="B" Value="50"  FillBrush="#FF06F906" FillEndBrush="#FF5CF95C"></wpfApplication11:AxisXDataModel>
                        <wpfApplication11:AxisXDataModel Name="C" Value="70"  FillBrush="Cyan" FillEndBrush="#FF4DFFFF"></wpfApplication11:AxisXDataModel>
                        <wpfApplication11:AxisXDataModel Name="D" Value="30" FillBrush="GreenYellow" FillEndBrush="#FFBFFD60"></wpfApplication11:AxisXDataModel>
                        <wpfApplication11:AxisXDataModel Name="E" Value="86" FillBrush="DarkOrchid" FillEndBrush="#FFCC73F7"></wpfApplication11:AxisXDataModel>
                        <wpfApplication11:AxisXDataModel Name="F" Value="60" FillBrush="Coral" FillEndBrush="#FFF9A181"></wpfApplication11:AxisXDataModel>
                    </wpfApplication11:AxisXModel.Datas>
                </wpfApplication11:AxisXModel>
            </wpfApplication11:BarChartControl.AxisX>
        </wpfApplication11:BarChartControl>
    </Grid>
</Window>
View Code

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 通過expr指令可以進行+、-、*、\、%等運算,但是有一點值得註意,使用乘法時,要在*前加上一個\符號。 通過test指令可以進行邏輯測試,進行測試的情況有四種: 1、整數測試 a、判斷兩個整數是否相等——test int1 -eq int2 b、判斷兩個整數是否不等——test int1 -ne ...
  • 1.下載Nginx:http://nginx.org/en/download.html 2.下載winsw配置包:http://files.cnblogs.com/files/objecttozero/nginx-service.zip 3.解壓zip文件 4.安裝 c:/nginx/nginx-s ...
  • 第一部分:安裝Mysql5.7 1.下載YUM庫 shell > wget http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm 2.安裝YUM庫 shell > yum localinstall -y mysql57 ...
  • 一、準備tomcat 拷貝一份tomcat mkdir -pvri liumj cp -pvri purse-fpadmin/* liumj purse-fpadmin/*拷到liumj目錄下 二、改tomcat配置文件 vim conf/server.xml 三、解壓jar包 路徑:tomcat/ ...
  • 註:此文僅針對mac系統如果你是mac用戶,會發現桌面經常一團糟,桌面到處都是平時的截圖(mac系統的截圖是command+shift+3 和 command+shift+4 兩個快捷命令) 之前一直只知道截圖的預設保存路徑是在桌面,每次都是只能默默地定時清理...今天受不了了,想看看能否修改保存的 ...
  • 原創作品,允許轉載,轉載時請務必以超鏈接形式標明文章、作者信息和本聲明,否則將追究法律責任。 眾所周知,vim是vi的增強版本,實際體驗要比vi好用很多,由於筆者為ARM系統製作的基於busybox的文件系統中只帶了vi工具,本文主要介紹怎麼移植vim工具到基於busybox的製作的rootfs中。 ...
  • 本人系統win7專業版64位。 從5月底開始就時不時有藍屏發生,而且可以說是沒有任何徵兆就“啪”的一下藍了... 有時候是隔個四五天藍屏一次,有時候一天都能藍好幾次,實在是讓人惱火。 從第一次藍屏就開始尋找原因,直到一個月前才查到元凶,竟然就是Networx。作為一個藍屏小白,我做了挺多嘗試才最終找 ...
  • 自定義標題欄 一、設計界面樣式 <UserControl x:Class="WpfApplication6.TitleListControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="htt ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...