WPF 自定义BarChartControl(可左右滑动的柱状图)
原文:WPF 自定义BarChartControl(可左右滑动的柱状图)

自定义可左右滑动、拖拽滑动的平面柱状图

在做这种样式控件之前,可先浏览我之前预研的控件:

A、自定义左右滑动ScrollViewer(可拖动滑动)

B、自定义Bar柱状图

OK,现在说下控件具体设计过程:

1)采用Grid布局,这样可以将Y轴的标题设置平均高度,X轴的柱子也可以平均。

  当然X轴也会存在一个问题,当数据较少时,只有俩个柱子难道就布满界面?

  很简单,在Grid中多添加一个ColumnDefinition就行了,柱子的宽度设置成可配置,额外的一个设置成默认填充。

2)Bar采用RadioButton,因为有Checked属性,之后整个控件SelectionChanged的事件源可以从这来

3)滑动条容器,我这边比较熟悉DevExpress控件,所以用的是ScrollBox,然后修改其中的模板。

其它的一些设置比较简单,就不说了,直接看代码

1、UserControl界面

<UserControl x:Class="BarChartControlDemo.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"xmlns:dxlc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol"mc:Ignorable="d" d:DesignHeight="100" d:DesignWidth="200" Loaded="BarChartControl_OnLoaded"><UserControl.Resources><Style x:Key="ScrollBarStyle1" TargetType="{x:Type ScrollBar}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type ScrollBar}"><Grid Height="0"></Grid></ControlTemplate></Setter.Value></Setter></Style><ControlTemplate x:Key="LightedBtnTemplate" TargetType="RadioButton"><Grid><Grid.RowDefinitions><RowDefinition Height="5"></RowDefinition><RowDefinition></RowDefinition><RowDefinition Height="5"></RowDefinition></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="5"></ColumnDefinition><ColumnDefinition></ColumnDefinition><ColumnDefinition Width="5"></ColumnDefinition></Grid.ColumnDefinitions><Rectangle Grid.Row="1" Grid.Column="1" Fill="{TemplateBinding Background}"></Rectangle><Grid x:Name="Grid_00" Grid.Row="0" Grid.Column="0"></Grid><Grid x:Name="Grid_02" Grid.Row="0" Grid.Column="2"></Grid><Grid x:Name="Grid_20" Grid.Row="2" Grid.Column="0"></Grid><Grid x:Name="Grid_22" Grid.Row="2" Grid.Column="2"></Grid><Grid x:Name="Grid_Top" Grid.Row="0" Grid.Column="1"></Grid><Grid x:Name="Grid_Bottom" Grid.Row="2" Grid.Column="1"></Grid><Grid x:Name="Grid_Left" Grid.Row="1" Grid.Column="0"></Grid><Grid x:Name="Grid_Right" Grid.Row="1" Grid.Column="2"></Grid></Grid><ControlTemplate.Triggers><Trigger Property="IsChecked" Value="True"><Setter TargetName="Grid_00" Property="Background"><Setter.Value><LinearGradientBrush StartPoint="1,1" EndPoint="0,0"><GradientStop Color="White" Offset="0"></GradientStop><GradientStop Color="Transparent" Offset="0.5"></GradientStop></LinearGradientBrush></Setter.Value></Setter><Setter TargetName="Grid_02" Property="Background"><Setter.Value><LinearGradientBrush StartPoint="0,1" EndPoint="1,0"><GradientStop Color="White" Offset="0"></GradientStop><GradientStop Color="Transparent" Offset="0.5"></GradientStop></LinearGradientBrush></Setter.Value></Setter><Setter TargetName="Grid_20" Property="Background"><Setter.Value><LinearGradientBrush StartPoint="1,0" EndPoint="0,1"><GradientStop Color="White" Offset="0"></GradientStop><GradientStop Color="Transparent" Offset="0.5"></GradientStop></LinearGradientBrush></Setter.Value></Setter><Setter TargetName="Grid_22" Property="Background"><Setter.Value><LinearGradientBrush StartPoint="0,0" EndPoint="1,1"><GradientStop Color="White" Offset="0"></GradientStop><GradientStop Color="Transparent" Offset="0.5"></GradientStop></LinearGradientBrush></Setter.Value></Setter><Setter TargetName="Grid_Top" Property="Background"><Setter.Value><LinearGradientBrush StartPoint="1,1" EndPoint="1,0"><GradientStop Color="White" Offset="0"></GradientStop><GradientStop Color="Transparent" Offset="1"></GradientStop></LinearGradientBrush></Setter.Value></Setter><Setter TargetName="Grid_Bottom" Property="Background"><Setter.Value><LinearGradientBrush StartPoint="1,0" EndPoint="1,1"><GradientStop Color="White" Offset="0"></GradientStop><GradientStop Color="Transparent" Offset="1"></GradientStop></LinearGradientBrush></Setter.Value></Setter><Setter TargetName="Grid_Left" Property="Background"><Setter.Value><LinearGradientBrush StartPoint="1,1" EndPoint="0,1"><GradientStop Color="White" Offset="0"></GradientStop><GradientStop Color="Transparent" Offset="1"></GradientStop></LinearGradientBrush></Setter.Value></Setter><Setter TargetName="Grid_Right" Property="Background"><Setter.Value><LinearGradientBrush StartPoint="0,1" EndPoint="1,1"><GradientStop Color="White" Offset="0"></GradientStop><GradientStop Color="Transparent" Offset="1"></GradientStop></LinearGradientBrush></Setter.Value></Setter></Trigger></ControlTemplate.Triggers></ControlTemplate></UserControl.Resources><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" Width="20"></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="MainGridFrom0To1Content" Grid.Row="0" Grid.RowSpan="3" Grid.Column="1"><dxlc:ScrollBox x:Name="MyScrollBoxFrom0To1" HorizontalScrollBarStyle="{StaticResource ScrollBarStyle1}" Padding="0" Margin="0"><Grid x:Name="MainBarContent" VerticalAlignment="Stretch"></Grid></dxlc:ScrollBox><Button x:Name="BtnLeft" Height="30" Margin="5" Opacity="0.5" Click="BtnLeft_OnClick" Background="Transparent" Content="向左滑" HorizontalAlignment="Left" Visibility="Visible"><Button.Template><ControlTemplate><Grid VerticalAlignment="Center"><Path Stroke="White" StrokeThickness="3" Data="m0,13 L13,0"></Path><Path Stroke="White" StrokeThickness="3" Data="m0,11 L13,24"></Path></Grid></ControlTemplate></Button.Template></Button><Button x:Name="BtnRight" Height="25" Margin="5" Click="BtnRight_OnClick" Background="Transparent" Content="向右滑" HorizontalAlignment="Right" Visibility="Visible"><Button.Template><ControlTemplate><Grid VerticalAlignment="Center"><Path Stroke="White" StrokeThickness="3" Data="m13,13 L0,0"></Path><Path Stroke="White" StrokeThickness="3" Data="m13,11 L0,24"></Path></Grid></ControlTemplate></Button.Template></Button></Grid><!--<Grid x:Name="RightGrid" Grid.Row="1" Grid.Column="2"></Grid>--><Grid x:Name="BottomGrid" Grid.Row="2" Grid.Column="1" Height="20"></Grid></Grid>
</UserControl>

View Code

2、UserControl后台

 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;HeaderGrid.Height = HeaderHeight;MainBarContent.Height = MyScrollBoxFrom0To1.ActualHeight - 17;LeftGrid.Width = AxisY.Width;SetYTitlesContent();SetXDatasContent();}private void SetXDatasContent(){var axisXModel = AxisX;if (axisXModel.Datas.Count > 0){int count = axisXModel.Datas.Count;double barArea = axisXModel.BarWidth + axisXModel.MarginWidth * 2;for (int i = 0; i < count + 1; i++){MainBarContent.ColumnDefinitions.Add(new ColumnDefinition(){Width = new GridLength(barArea)});}int index = 0;foreach (var data in axisXModel.Datas){//主内容var stackPanel = new StackPanel();stackPanel.Orientation = Orientation.Vertical;var tbl = new TextBlock();tbl.Height = 15;tbl.Text = data.Value.ToString();tbl.Foreground = axisXModel.ForeGround;tbl.HorizontalAlignment = HorizontalAlignment.Center;stackPanel.Children.Add(tbl);var radioButton = new RadioButton();radioButton.Template = (ControlTemplate)this.Resources["LightedBtnTemplate"];radioButton.Width = axisXModel.BarWidth;double maxValue = AxisY.Titles.Max(i => i.Value);radioButton.Height = (data.Value / maxValue) * (this.ActualHeight - BottomGrid.Height - HeaderHeight + 10);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}}       };radioButton.Background = linearBrush;radioButton.HorizontalAlignment = HorizontalAlignment.Center;radioButton.Click += RadioButton_OnClick;stackPanel.Children.Add(radioButton);//底部var bottomTbl = new TextBlock();bottomTbl.Text = data.Name;bottomTbl.Foreground = axisXModel.ForeGround;bottomTbl.VerticalAlignment = VerticalAlignment.Center;bottomTbl.TextAlignment = TextAlignment.Center;bottomTbl.HorizontalAlignment = HorizontalAlignment.Center;double textBlockWidth = axisXModel.LabelWidth;bottomTbl.Width = axisXModel.LabelWidth;stackPanel.Children.Add(bottomTbl);Grid.SetColumn(stackPanel, index);stackPanel.Margin = new Thickness(0, 0, -textBlockWidth / 2, -17);stackPanel.VerticalAlignment = VerticalAlignment.Bottom;stackPanel.HorizontalAlignment = HorizontalAlignment.Right;MainBarContent.Children.Add(stackPanel);MainBarContent.Background = Brushes.Transparent;index++;}double mainBarContentWidth = count * barArea;if (mainBarContentWidth > MainGridFrom0To1Content.ActualWidth){BtnLeft.Visibility = Visibility.Visible;BtnRight.Visibility = Visibility.Visible;}}}public delegate void BarSelectionChangedEventArgs(object sender, RoutedEventArgs e);public event BarSelectionChangedEventArgs BarSelectionChanged;private void RadioButton_OnClick(object sender, RoutedEventArgs e){var currentButton = sender as RadioButton;foreach (var element in MainBarContent.Children){var stackPanel = element as StackPanel;var button = stackPanel.Children[1] as RadioButton;if (button != currentButton){button.IsChecked = false;}}if (BarSelectionChanged!=null){BarSelectionChanged(sender, e);}}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 = axisYModel.LabelHeight;if (index < gridRows){textblock.VerticalAlignment = VerticalAlignment.Bottom;textblock.Margin = new Thickness(0, 0, 5, -axisYModel.LabelHeight / 2);//因为设置在行底部还不够,必须往下移Grid.SetRow(textblock, gridRows - index - 1);}else{textblock.VerticalAlignment = VerticalAlignment.Top;textblock.Margin = new Thickness(0, -axisYModel.LabelHeight / 2, 5, 0);//最后一个,设置在顶部Grid.SetRow(textblock, 0);}LeftGrid.Children.Add(textblock);var border = new Border();border.Height = axisYModel.LineHeight;border.BorderBrush = axisYModel.LineBrush;double thickness = Convert.ToDouble(axisYModel.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());}}/// <summary>/// 向左滑动/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void BtnLeft_OnClick(object sender, RoutedEventArgs e){var startOffset = MyScrollBoxFrom0To1.HorizontalOffset;if (startOffset <= _lastHorizontalOffset){MyScrollBoxFrom0To1.HorizontalOffset = startOffset - 100;_lastHorizontalOffset = startOffset - 100;}else if (startOffset > _lastHorizontalOffset){BtnLeft.Opacity = 0.5;}BtnRight.Opacity = 1;}private double _lastHorizontalOffset = 0;/// <summary>/// 向右滑动/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void BtnRight_OnClick(object sender, RoutedEventArgs e){var startOffset = MyScrollBoxFrom0To1.HorizontalOffset;if (startOffset >= _lastHorizontalOffset){MyScrollBoxFrom0To1.HorizontalOffset = startOffset + 100;_lastHorizontalOffset = startOffset + 100;}else if (startOffset < _lastHorizontalOffset){BtnRight.Opacity = 0.5;}BtnLeft.Opacity = 1;}}#region XDataModelpublic class AxisXModel{private double _labelWidth = 20;/// <summary>/// 底部标签-单个宽度/// </summary>public double LabelWidth{get { return _labelWidth; }set { _labelWidth = value; }}private double _marginWidth = 20;/// <summary>/// Bar间隔宽度/// </summary>public double MarginWidth{get { return _marginWidth; }set { _marginWidth = value; }}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; }}private double _barWidth = 30;/// <summary>/// Bar宽度/// </summary>public double BarWidth{get { return _barWidth; }set { _barWidth = value; }}List<AxisXDataModel> _datas = new List<AxisXDataModel>();/// <summary>/// 数据/// </summary>public List<AxisXDataModel> Datas{get { return _datas; }set { _datas = value; }}}public class AxisXDataModel : DataModel{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; }}}#endregion#region YDataModelpublic 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; } }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; }}List<AxisYDataModel> _titles = new List<AxisYDataModel>();/// <summary>/// 左侧标题列表/// </summary>public List<AxisYDataModel> Titles{get { return _titles; }set { _titles = value; }}}public class AxisYDataModel : DataModel{}#endregionpublic class DataModel{/// <summary>/// 显示名称/// </summary>public string Name { get; set; }/// <summary>/// 值/// </summary>public double Value { get; set; }}

View Code

3、控件引用

    <barChartControlDemo:BarChartControl BorderBrush="White" Width="500" Height="200" BorderThickness="2,0,2,0" HeaderHeight="20" BarSelectionChanged="BarChartControl_OnBarSelectionChanged"><barChartControlDemo:BarChartControl.AxisY><barChartControlDemo:AxisYModel Width="30" ForeGround="White"><barChartControlDemo:AxisYModel.Titles><barChartControlDemo:AxisYDataModel Name="0" Value="0"></barChartControlDemo:AxisYDataModel><barChartControlDemo:AxisYDataModel Name="20" Value="20"></barChartControlDemo:AxisYDataModel><barChartControlDemo:AxisYDataModel Name="40" Value="40"></barChartControlDemo:AxisYDataModel><barChartControlDemo:AxisYDataModel Name="60" Value="60"></barChartControlDemo:AxisYDataModel><barChartControlDemo:AxisYDataModel Name="80" Value="80"></barChartControlDemo:AxisYDataModel><barChartControlDemo:AxisYDataModel Name="100" Value="100"></barChartControlDemo:AxisYDataModel></barChartControlDemo:AxisYModel.Titles></barChartControlDemo:AxisYModel></barChartControlDemo:BarChartControl.AxisY><barChartControlDemo:BarChartControl.AxisX><barChartControlDemo:AxisXModel Height="30" ForeGround="White" LabelWidth="60"><barChartControlDemo:AxisXModel.Datas><barChartControlDemo:AxisXDataModel Name="C#" Value="100" FillBrush="#FF2C87AC" FillEndBrush="SkyBlue"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Java" Value="20" FillBrush="#FF04A856" FillEndBrush="SpringGreen"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Php" Value="40" FillBrush="DodgerBlue" FillEndBrush="#FF60B0FD"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Winform" Value="79" FillBrush="#FFF70B0B" FillEndBrush="#FFFD7F7F"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Silverlight" Value="98" FillBrush="#FF6EA816" FillEndBrush="GreenYellow"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Mvc" Value="60" FillBrush="#FF6EA816" FillEndBrush="GreenYellow"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Python" Value="81" FillBrush="#FFF70B0B" FillEndBrush="#FFFD7F7F"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Ruby" Value="0" FillBrush="DodgerBlue" FillEndBrush="#FF60B0FD"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Linux" Value="99" FillBrush="DodgerBlue" FillEndBrush="#FF60B0FD"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="VB" Value="45" FillBrush="DodgerBlue" FillEndBrush="#FF60B0FD"></barChartControlDemo:AxisXDataModel></barChartControlDemo:AxisXModel.Datas></barChartControlDemo:AxisXModel></barChartControlDemo:BarChartControl.AxisX></barChartControlDemo:BarChartControl>

View Code

GitHub下载地址:https://github.com/Kybs0/BarChartControlDemo/

如果需要不同的柱状图叠加:

Demo如下

UserControl:

<UserControl x:Class="BarChartControlDemo.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"xmlns:dxlc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol"mc:Ignorable="d" d:DesignHeight="100" d:DesignWidth="200" Loaded="BarChartControl_OnLoaded"><UserControl.Resources><Style x:Key="ScrollBarStyle1" TargetType="{x:Type ScrollBar}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type ScrollBar}"><Grid Height="0"></Grid></ControlTemplate></Setter.Value></Setter></Style><ControlTemplate x:Key="LightedBtnTemplate" TargetType="RadioButton"><Grid Margin="-5"><Grid.RowDefinitions><RowDefinition Height="5"></RowDefinition><RowDefinition></RowDefinition><RowDefinition Height="5"></RowDefinition></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="5"></ColumnDefinition><ColumnDefinition></ColumnDefinition><ColumnDefinition Width="5"></ColumnDefinition></Grid.ColumnDefinitions><Rectangle Grid.Row="1" Grid.Column="1" Fill="{TemplateBinding Background}"></Rectangle><Grid x:Name="Grid_00" Grid.Row="0" Grid.Column="0"></Grid><Grid x:Name="Grid_02" Grid.Row="0" Grid.Column="2"></Grid><Grid x:Name="Grid_20" Grid.Row="2" Grid.Column="0"></Grid><Grid x:Name="Grid_22" Grid.Row="2" Grid.Column="2"></Grid><Grid x:Name="Grid_Top" Grid.Row="0" Grid.Column="1"></Grid><Grid x:Name="Grid_Bottom" Grid.Row="2" Grid.Column="1"></Grid><Grid x:Name="Grid_Left" Grid.Row="1" Grid.Column="0"></Grid><Grid x:Name="Grid_Right" Grid.Row="1" Grid.Column="2"></Grid></Grid><ControlTemplate.Triggers><Trigger Property="IsChecked" Value="True"><Setter TargetName="Grid_00" Property="Background"><Setter.Value><LinearGradientBrush StartPoint="1,1" EndPoint="0,0"><GradientStop Color="White" Offset="0"></GradientStop><GradientStop Color="Transparent" Offset="0.5"></GradientStop></LinearGradientBrush></Setter.Value></Setter><Setter TargetName="Grid_02" Property="Background"><Setter.Value><LinearGradientBrush StartPoint="0,1" EndPoint="1,0"><GradientStop Color="White" Offset="0"></GradientStop><GradientStop Color="Transparent" Offset="0.5"></GradientStop></LinearGradientBrush></Setter.Value></Setter><Setter TargetName="Grid_20" Property="Background"><Setter.Value><LinearGradientBrush StartPoint="1,0" EndPoint="0,1"><GradientStop Color="White" Offset="0"></GradientStop><GradientStop Color="Transparent" Offset="0.5"></GradientStop></LinearGradientBrush></Setter.Value></Setter><Setter TargetName="Grid_22" Property="Background"><Setter.Value><LinearGradientBrush StartPoint="0,0" EndPoint="1,1"><GradientStop Color="White" Offset="0"></GradientStop><GradientStop Color="Transparent" Offset="0.5"></GradientStop></LinearGradientBrush></Setter.Value></Setter><Setter TargetName="Grid_Top" Property="Background"><Setter.Value><LinearGradientBrush StartPoint="1,1" EndPoint="1,0"><GradientStop Color="White" Offset="0"></GradientStop><GradientStop Color="Transparent" Offset="1"></GradientStop></LinearGradientBrush></Setter.Value></Setter><Setter TargetName="Grid_Bottom" Property="Background"><Setter.Value><LinearGradientBrush StartPoint="1,0" EndPoint="1,1"><GradientStop Color="White" Offset="0"></GradientStop><GradientStop Color="Transparent" Offset="1"></GradientStop></LinearGradientBrush></Setter.Value></Setter><Setter TargetName="Grid_Left" Property="Background"><Setter.Value><LinearGradientBrush StartPoint="1,1" EndPoint="0,1"><GradientStop Color="White" Offset="0"></GradientStop><GradientStop Color="Transparent" Offset="1"></GradientStop></LinearGradientBrush></Setter.Value></Setter><Setter TargetName="Grid_Right" Property="Background"><Setter.Value><LinearGradientBrush StartPoint="0,1" EndPoint="1,1"><GradientStop Color="White" Offset="0"></GradientStop><GradientStop Color="Transparent" Offset="1"></GradientStop></LinearGradientBrush></Setter.Value></Setter></Trigger></ControlTemplate.Triggers></ControlTemplate></UserControl.Resources><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" Width="20"></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="MainGridFrom0To1Content" Grid.Row="0" Grid.RowSpan="3" Grid.Column="1"><dxlc:ScrollBox x:Name="MyScrollBoxFrom0To1" HorizontalScrollBarStyle="{StaticResource ScrollBarStyle1}" Padding="0" Margin="0"><Grid x:Name="MainBarContent" VerticalAlignment="Stretch"></Grid></dxlc:ScrollBox><Button x:Name="BtnLeft" Height="30" Margin="5" Opacity="0.5" Click="BtnLeft_OnClick" Background="Transparent" Content="向左滑" HorizontalAlignment="Left" Visibility="Visible"><Button.Template><ControlTemplate><Grid VerticalAlignment="Center"><Path Stroke="White" StrokeThickness="3" Data="m0,13 L13,0"></Path><Path Stroke="White" StrokeThickness="3" Data="m0,11 L13,24"></Path></Grid></ControlTemplate></Button.Template></Button><Button x:Name="BtnRight" Height="25" Margin="5" Click="BtnRight_OnClick" Background="Transparent" Content="向右滑" HorizontalAlignment="Right" Visibility="Visible"><Button.Template><ControlTemplate><Grid VerticalAlignment="Center"><Path Stroke="White" StrokeThickness="3" Data="m13,13 L0,0"></Path><Path Stroke="White" StrokeThickness="3" Data="m13,11 L0,24"></Path></Grid></ControlTemplate></Button.Template></Button></Grid><!--<Grid x:Name="RightGrid" Grid.Row="1" Grid.Column="2"></Grid>--><Grid x:Name="BottomGrid" Grid.Row="2" Grid.Column="1" Height="20"></Grid></Grid>
</UserControl>

View Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;namespace BarChartControlDemo
{/// <summary>/// Interaction logic for 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;HeaderGrid.Height = HeaderHeight;MainBarContent.Height = MyScrollBoxFrom0To1.ActualHeight - 17;LeftGrid.Width = AxisY.Width;SetYTitlesContent();SetXDatasContent();}private void SetXDatasContent(){var axisXModel = AxisX;if (axisXModel.Datas.Count > 0){int count = axisXModel.Datas[0].Datas.Count;double barArea = axisXModel.BarWidth + axisXModel.MarginWidth * 2;for (int i = 0; i < count + 1; i++){MainBarContent.ColumnDefinitions.Add(new ColumnDefinition(){Width = new GridLength(barArea)});}for (int index = 0; index < axisXModel.Datas[0].Datas.Count; index++){//主内容var stackPanel = new StackPanel();stackPanel.Orientation = Orientation.Vertical;var tbl = new TextBlock();tbl.Height = 15;tbl.Text = string.Empty;if (axisXModel.Datas.Count<=1){tbl.Text = axisXModel.Datas[0].Datas[index].ToString();}tbl.Foreground = axisXModel.ForeGround;tbl.HorizontalAlignment = HorizontalAlignment.Center;tbl.Margin=new Thickness(0,0,0,5);stackPanel.Children.Add(tbl);double allChartHeight = this.ActualHeight - BottomGrid.Height - HeaderHeight;foreach (var data in axisXModel.Datas){var currentChartData = data.Datas[index];var radioButton = new RadioButton();radioButton.Template = (ControlTemplate)this.Resources["LightedBtnTemplate"];radioButton.Width = axisXModel.BarWidth;double maxValue = AxisY.Titles.Max(i => i.Value);radioButton.Height = (currentChartData.Value / maxValue) * allChartHeight;var linearBrush = new LinearGradientBrush(){StartPoint = new Point(1, 0),EndPoint = new Point(1, 1),GradientStops = new GradientStopCollection() { new GradientStop(){Color = currentChartData.FillBrush, Offset = 0}, new GradientStop(){Color = currentChartData.FillEndBrush, Offset = 1}}};radioButton.Background = linearBrush;radioButton.HorizontalAlignment = HorizontalAlignment.Center;radioButton.Click += RadioButton_OnClick;stackPanel.Children.Add(radioButton);}//底部var bottomTbl = new TextBlock();bottomTbl.Text = axisXModel.Datas[0].Datas[index].Name;bottomTbl.Foreground = axisXModel.ForeGround;bottomTbl.VerticalAlignment = VerticalAlignment.Center;bottomTbl.TextAlignment = TextAlignment.Center;bottomTbl.HorizontalAlignment = HorizontalAlignment.Center;double textBlockWidth = axisXModel.LabelWidth;bottomTbl.Width = axisXModel.LabelWidth;bottomTbl.Margin = new Thickness(0, 5, 0, 0);stackPanel.Children.Add(bottomTbl);Grid.SetColumn(stackPanel, index);stackPanel.Margin = new Thickness(0, 0, -textBlockWidth / 2, -17);stackPanel.VerticalAlignment = VerticalAlignment.Bottom;stackPanel.HorizontalAlignment = HorizontalAlignment.Right;MainBarContent.Children.Add(stackPanel);MainBarContent.Background = Brushes.Transparent;}double mainBarContentWidth = count * barArea;if (mainBarContentWidth > MainGridFrom0To1Content.ActualWidth){BtnLeft.Visibility = Visibility.Visible;BtnRight.Visibility = Visibility.Visible;}}}public delegate void BarSelectionChangedEventArgs(object sender, RoutedEventArgs e);public event BarSelectionChangedEventArgs BarSelectionChanged;private void RadioButton_OnClick(object sender, RoutedEventArgs e){var currentButton = sender as RadioButton;foreach (var element in MainBarContent.Children){var stackPanel = element as StackPanel;foreach (var child in stackPanel.Children){if (child is RadioButton&& child !=currentButton){(child as RadioButton).IsChecked = false;}}}if (BarSelectionChanged!=null){BarSelectionChanged(sender, e);}}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 = axisYModel.LabelHeight;if (index < gridRows){textblock.VerticalAlignment = VerticalAlignment.Bottom;textblock.Margin = new Thickness(0, 0, 5, -axisYModel.LabelHeight / 2);//因为设置在行底部还不够,必须往下移Grid.SetRow(textblock, gridRows - index - 1);}else{textblock.VerticalAlignment = VerticalAlignment.Top;textblock.Margin = new Thickness(0, -axisYModel.LabelHeight / 2, 5, 0);//最后一个,设置在顶部Grid.SetRow(textblock, 0);}LeftGrid.Children.Add(textblock);var border = new Border();border.Height = axisYModel.LineHeight;border.BorderBrush = axisYModel.LineBrush;double thickness = Convert.ToDouble(axisYModel.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());}}/// <summary>/// 向左滑动/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void BtnLeft_OnClick(object sender, RoutedEventArgs e){var startOffset = MyScrollBoxFrom0To1.HorizontalOffset;if (startOffset <= _lastHorizontalOffset){MyScrollBoxFrom0To1.HorizontalOffset = startOffset - 100;_lastHorizontalOffset = startOffset - 100;}else if (startOffset > _lastHorizontalOffset){BtnLeft.Opacity = 0.5;}BtnRight.Opacity = 1;}private double _lastHorizontalOffset = 0;/// <summary>/// 向右滑动/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void BtnRight_OnClick(object sender, RoutedEventArgs e){var startOffset = MyScrollBoxFrom0To1.HorizontalOffset;if (startOffset >= _lastHorizontalOffset){MyScrollBoxFrom0To1.HorizontalOffset = startOffset + 100;_lastHorizontalOffset = startOffset + 100;}else if (startOffset < _lastHorizontalOffset){BtnRight.Opacity = 0.5;}BtnLeft.Opacity = 1;}}#region XDataModelpublic class AxisXModel{private double _labelWidth = 20;/// <summary>/// 底部标签-单个宽度/// </summary>public double LabelWidth{get { return _labelWidth; }set { _labelWidth = value; }}private double _marginWidth = 20;/// <summary>/// Bar间隔宽度/// </summary>public double MarginWidth{get { return _marginWidth; }set { _marginWidth = value; }}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; }}private double _barWidth = 30;/// <summary>/// Bar宽度/// </summary>public double BarWidth{get { return _barWidth; }set { _barWidth = value; }}List<AxisXData> _datas = new List<AxisXData>();/// <summary>/// 数据集合/// </summary>public List<AxisXData> Datas{get { return _datas; }set { _datas = value; }}}/// <summary>/// 一组数据/// </summary>public class AxisXData{public string Name { get; set; }List<AxisXDataModel> _dataModels = new List<AxisXDataModel>();/// <summary>/// 数据/// </summary>public List<AxisXDataModel> Datas{get { return _dataModels; }set { _dataModels = value; }}}public class AxisXDataModel : DataModel{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; }}}#endregion#region YDataModelpublic 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; } }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; }}List<AxisYDataModel> _titles = new List<AxisYDataModel>();/// <summary>/// 左侧标题列表/// </summary>public List<AxisYDataModel> Titles{get { return _titles; }set { _titles = value; }}}public class AxisYDataModel : DataModel{}#endregionpublic class DataModel{/// <summary>/// 显示名称/// </summary>public string Name { get; set; }/// <summary>/// 值/// </summary>public double Value { get; set; }}
}

View Code

界面引用:

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:barChartControlDemo="clr-namespace:BarChartControlDemo"x:Class="BarChartControlDemo.MainWindow"
Title="MainWindow" Height="350" Width="600" Background="#FF8181C5"><Grid><barChartControlDemo:BarChartControl BorderBrush="White" Width="500" Height="200" BorderThickness="2,0,2,0" HeaderHeight="20" BarSelectionChanged="BarChartControl_OnBarSelectionChanged"><barChartControlDemo:BarChartControl.AxisY><barChartControlDemo:AxisYModel Width="30" ForeGround="White"><barChartControlDemo:AxisYModel.Titles><barChartControlDemo:AxisYDataModel Name="0" Value="0"></barChartControlDemo:AxisYDataModel><barChartControlDemo:AxisYDataModel Name="20" Value="20"></barChartControlDemo:AxisYDataModel><barChartControlDemo:AxisYDataModel Name="40" Value="40"></barChartControlDemo:AxisYDataModel><barChartControlDemo:AxisYDataModel Name="60" Value="60"></barChartControlDemo:AxisYDataModel><barChartControlDemo:AxisYDataModel Name="80" Value="80"></barChartControlDemo:AxisYDataModel><barChartControlDemo:AxisYDataModel Name="100" Value="100"></barChartControlDemo:AxisYDataModel></barChartControlDemo:AxisYModel.Titles></barChartControlDemo:AxisYModel></barChartControlDemo:BarChartControl.AxisY><barChartControlDemo:BarChartControl.AxisX><barChartControlDemo:AxisXModel Height="30" ForeGround="White" LabelWidth="60"><barChartControlDemo:AxisXModel.Datas><barChartControlDemo:AxisXData Name="第一组数据"><barChartControlDemo:AxisXData.Datas><barChartControlDemo:AxisXDataModel Name="C#" Value="100" FillBrush="#FF2C87AC" FillEndBrush="SkyBlue"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Java" Value="20" FillBrush="#FF04A856" FillEndBrush="SpringGreen"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Php" Value="40" FillBrush="DodgerBlue" FillEndBrush="#FF60B0FD"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Winform" Value="79" FillBrush="#FFF70B0B" FillEndBrush="#FFFD7F7F"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Silverlight" Value="98" FillBrush="#FF6EA816" FillEndBrush="GreenYellow"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Mvc" Value="60" FillBrush="#FF6EA816" FillEndBrush="GreenYellow"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Python" Value="81" FillBrush="#FFF70B0B" FillEndBrush="#FFFD7F7F"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Ruby" Value="0" FillBrush="DodgerBlue" FillEndBrush="#FF60B0FD"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Linux" Value="99" FillBrush="DodgerBlue" FillEndBrush="#FF60B0FD"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="VB" Value="45" FillBrush="DodgerBlue" FillEndBrush="#FF60B0FD"></barChartControlDemo:AxisXDataModel></barChartControlDemo:AxisXData.Datas> </barChartControlDemo:AxisXData><barChartControlDemo:AxisXData Name="第二组数据"><barChartControlDemo:AxisXData.Datas><barChartControlDemo:AxisXDataModel Name="C#" Value="0" FillBrush="#FFF70B0B" FillEndBrush="#FFFD7F7F"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Java" Value="20" FillBrush="DodgerBlue" FillEndBrush="#FF60B0FD"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Php" Value="40"  FillBrush="#FF6EA816" FillEndBrush="GreenYellow"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Winform" Value="10" FillBrush="DodgerBlue" FillEndBrush="#FF60B0FD"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Silverlight" Value="1" FillBrush="DodgerBlue" FillEndBrush="#FF60B0FD"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Mvc" Value="0"  FillBrush="DodgerBlue" FillEndBrush="#FF60B0FD"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Python" Value="2" FillBrush="DodgerBlue" FillEndBrush="#FF60B0FD"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Ruby" Value="20" FillBrush="Blue" FillEndBrush="CadetBlue"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="Linux" Value="1" FillBrush="BlueViolet" FillEndBrush="PaleVioletRed"></barChartControlDemo:AxisXDataModel><barChartControlDemo:AxisXDataModel Name="VB" Value="20"  FillBrush="CornflowerBlue" FillEndBrush="PowderBlue"></barChartControlDemo:AxisXDataModel></barChartControlDemo:AxisXData.Datas></barChartControlDemo:AxisXData></barChartControlDemo:AxisXModel.Datas></barChartControlDemo:AxisXModel></barChartControlDemo:BarChartControl.AxisX></barChartControlDemo:BarChartControl></Grid>
</Window>

View Code

注:此案例需要下载DevExpress控件~

posted on 2018-09-25 08:54 NET未来之路 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/9697812.html

WPF 自定义BarChartControl(可左右滑动的柱状图)相关推荐

  1. WPF自定义空心文字

    原文:WPF自定义空心文字 首先创建一个自定义控件,继承自FrameworkElement,"Generic.xaml"中可以不添加样式. 要自定义空心文字,要用到绘制格式化文本F ...

  2. WPF 自定义标题栏 自定义菜单栏

    原文:WPF 自定义标题栏 自定义菜单栏 自定义标题栏 自定义列表,可以直接修改WPF中的ListBox模板,也用这样类似的效果.但是ListBox是不能设置默认选中状态的. 而我们需要一些复杂的UI ...

  3. [WPF]自定义鼠标指针

    [WPF]自定义鼠标指针 原文:[WPF]自定义鼠标指针 [WPF]自定义鼠标指针 周银辉 看看WPF Cursor类的两个构造函数吧: public Cursor(Stream cursorStre ...

  4. WPF自定义命令(转)

    WPF自定义命令 自定义命令,可以分为两个层次来理解 1.声明自己的RoutedCommand实例,这个层次比较浅 2.从实现ICommand接口开始,这个才算的上真正的自定义命令 自定义命令的目的是 ...

  5. android 自定义view滚动条,Android自定义View实现等级滑动条的实例

    Android自定义View实现等级滑动条的实例 实现效果图: 思路: 首先绘制直线,然后等分直线绘制点: 绘制点的时候把X值存到集合中. 然后绘制背景图片,以及图片上的数字. 点击事件down的时候 ...

  6. WPF 自定义 MessageBox (相对完善版 v1.0.0.6)

    基于WPF的自定义 MessageBox. 众所周知WPF界面美观.大多数WPF元素都可以简单的修改其样式,从而达到程序的风格统一.可是当你不得不弹出一个消息框通知用户消息时(虽然很不建议在程序中频繁 ...

  7. 【C#】wpf自定义calendar日期选择控件的样式

    原文:[C#]wpf自定义calendar日期选择控件的样式 首先上图看下样式 原理 总览 ItemsControl内容的生成 实现 界面的实现 后台ViewModel的实现 首先上图,看下样式 原理 ...

  8. wpf 自定义窗口,最大化时覆盖任务栏解决方案

    原文:wpf 自定义窗口,最大化时覆盖任务栏解决方案 相信很多人使用wpf时会选择自定义美观的窗口,因此会设置WindowStyle="None" 取消自带的标题栏.但这样使用 W ...

  9. WPF自定义开关切换按钮

    WPF自定义开关切换按钮 突发奇想先要自己写一个开关按钮,说干就开干了,以下为View视图布局代码,开关按钮的样式就直接在这里定义了,主要呢通过定义触发器来完成按钮的切换. ```csharp < ...

最新文章

  1. python输出文字加数字_python变量、输入、输出、数字、字符串
  2. 机器学习知识点(四)最小二乘法Java实现
  3. Windows线程同步机制的区别与比较及进程通信方法
  4. linux线程同步(5)-屏障
  5. zoj3381 Osaisen Choudai!
  6. poj 1064 Cable master
  7. tp5 html获取get,tp5获取请求参数
  8. android 输入金额,EditText输入金额保留两位小数点
  9. 01.QT中点击弹出新页面
  10. python flask web部署_webapp开发之使用apache部署python flask webapp
  11. 地理信息系统概论_2021考研专业课地理信息系统概论(黄杏元版)知识点总结(五)...
  12. 博科光纤交换机操作手册之三
  13. 3D 空间音效+空气衰减+人声模糊
  14. 美国计算机访学,计算机应用专业4天喜获美国加州大学洛杉矶分校访问学者职位...
  15. 我收藏的一些RSS订阅频道
  16. python实现触摸精灵功能_触摸精灵实现找图功能
  17. 前后端不分离,分页器组件(python-dango)
  18. Windows11创建删除账户以及用户权限的相关问题
  19. 2021年中国驴行业存栏量延续下降走势,存栏基数降低使得驴肉供应减少,价格持续走强[图]
  20. win2003服务器安全设置技术实例(二)

热门文章

  1. 控件包含代码块(即% ... %),因此无法修改控件集合解决
  2. 【MyBatis笔记】10-多对一左连接查询分步查询(查询所有订单及订单对应的客户)
  3. 校招刷题---java选择题笔记05
  4. Linux下解压rar格式文件
  5. flex中移除由MXML标签添加的侦听
  6. 小程序 getphonenumber_小程序入门,看这一篇就够了!
  7. android获取电量的方法,在Android中获取电池电量和状态
  8. HNU 程序设计 飞机起飞时间安排
  9. php正则表达式修正符,深入解析PHP正则模式修正符
  10. 数据结构 5-3-2 二叉树前序中序后序遍历非递归实现