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

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

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>

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 - ;
LeftGrid.Width = AxisY.Width; SetYTitlesContent(); SetXDatasContent();
} private void SetXDatasContent()
{
var axisXModel = AxisX;
if (axisXModel.Datas.Count > )
{
int count = axisXModel.Datas.Count;
double barArea = axisXModel.BarWidth + axisXModel.MarginWidth * ; for (int i = ; i < count + ; i++)
{
MainBarContent.ColumnDefinitions.Add(new ColumnDefinition()
{
Width = new GridLength(barArea)
});
}
int index = ;
foreach (var data in axisXModel.Datas)
{
//主内容
var stackPanel = new StackPanel();
stackPanel.Orientation = Orientation.Vertical; var tbl = new TextBlock();
tbl.Height = ;
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 + );
var linearBrush = new LinearGradientBrush()
{
StartPoint = new Point(, ),
EndPoint = new Point(, ),
GradientStops = new GradientStopCollection() {
new GradientStop()
{
Color = data.FillBrush, Offset =
}, new GradientStop()
{
Color = data.FillEndBrush, Offset =
}
}
};
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(, , -textBlockWidth / , -);
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[] as RadioButton;
if (button != currentButton)
{
button.IsChecked = false;
}
}
if (BarSelectionChanged!=null)
{
BarSelectionChanged(sender, e);
}
}
private void SetYTitlesContent()
{
var axisYModel = AxisY;
if (axisYModel.Titles.Count > )
{
int gridRows = axisYModel.Titles.Count - ;
for (int i = ; i < gridRows; i++)
{
LeftGrid.RowDefinitions.Add(new RowDefinition());
MainGridForRow1.RowDefinitions.Add(new RowDefinition());
}
int index = ;
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(, , , -axisYModel.LabelHeight / );//因为设置在行底部还不够,必须往下移
Grid.SetRow(textblock, gridRows - index - );
}
else
{
textblock.VerticalAlignment = VerticalAlignment.Top;
textblock.Margin = new Thickness(, -axisYModel.LabelHeight / , , );//最后一个,设置在顶部
Grid.SetRow(textblock, );
}
LeftGrid.Children.Add(textblock); var border = new Border();
border.Height = axisYModel.LineHeight;
border.BorderBrush = axisYModel.LineBrush;
double thickness = Convert.ToDouble(axisYModel.LineHeight) / ;
border.BorderThickness = new Thickness(, thickness, , thickness);
if (index < gridRows)
{
border.VerticalAlignment = VerticalAlignment.Bottom;
border.Margin = new Thickness(, , , -thickness);//因为设置在行底部还不够,必须往下移
Grid.SetRow(border, gridRows - index - );
}
else
{
border.VerticalAlignment = VerticalAlignment.Top;
border.Margin = new Thickness(, -thickness, , );//最后一个,设置在顶部
Grid.SetRow(border, );
}
Grid.SetColumn(border, );
Grid.SetColumnSpan(border, AxisX.Datas.Count + );
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 = ; 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 - ;
_lastHorizontalOffset = startOffset - ;
}
else if (startOffset > _lastHorizontalOffset)
{
BtnLeft.Opacity = 0.5;
}
BtnRight.Opacity = ;
} private double _lastHorizontalOffset = ;
/// <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 + ;
_lastHorizontalOffset = startOffset + ;
}
else if (startOffset < _lastHorizontalOffset)
{
BtnRight.Opacity = 0.5;
}
BtnLeft.Opacity = ;
}
}
#region XDataModel
public class AxisXModel
{
private double _labelWidth = ;
/// <summary>
/// 底部标签-单个宽度
/// </summary>
public double LabelWidth
{
get { return _labelWidth; }
set { _labelWidth = value; }
}
private double _marginWidth = ;
/// <summary>
/// Bar间隔宽度
/// </summary>
public double MarginWidth
{
get { return _marginWidth; }
set { _marginWidth = value; }
}
private double _height = ;
/// <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 = ;
/// <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 YDataModel
public class AxisYModel
{
private double _width = ;
/// <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 = ;
/// <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
{ }
#endregion public class DataModel
{
/// <summary>
/// 显示名称
/// </summary>
public string Name { get; set; } /// <summary>
/// 值
/// </summary>
public double Value { get; set; }
}

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>

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>
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 - ;
LeftGrid.Width = AxisY.Width; SetYTitlesContent(); SetXDatasContent();
} private void SetXDatasContent()
{
var axisXModel = AxisX;
if (axisXModel.Datas.Count > )
{
int count = axisXModel.Datas[].Datas.Count;
double barArea = axisXModel.BarWidth + axisXModel.MarginWidth * ; for (int i = ; i < count + ; i++)
{
MainBarContent.ColumnDefinitions.Add(new ColumnDefinition()
{
Width = new GridLength(barArea)
});
}
for (int index = ; index < axisXModel.Datas[].Datas.Count; index++)
{
//主内容
var stackPanel = new StackPanel();
stackPanel.Orientation = Orientation.Vertical; var tbl = new TextBlock();
tbl.Height = ;
tbl.Text = string.Empty;
if (axisXModel.Datas.Count<=)
{
tbl.Text = axisXModel.Datas[].Datas[index].ToString();
}
tbl.Foreground = axisXModel.ForeGround;
tbl.HorizontalAlignment = HorizontalAlignment.Center;
tbl.Margin=new Thickness(,,,);
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(, ),
EndPoint = new Point(, ),
GradientStops = new GradientStopCollection() {
new GradientStop()
{
Color = currentChartData.FillBrush, Offset =
}, new GradientStop()
{
Color = currentChartData.FillEndBrush, Offset =
}
}
};
radioButton.Background = linearBrush;
radioButton.HorizontalAlignment = HorizontalAlignment.Center;
radioButton.Click += RadioButton_OnClick;
stackPanel.Children.Add(radioButton);
} //底部
var bottomTbl = new TextBlock();
bottomTbl.Text = axisXModel.Datas[].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(, , , ); stackPanel.Children.Add(bottomTbl);
Grid.SetColumn(stackPanel, index);
stackPanel.Margin = new Thickness(, , -textBlockWidth / , -);
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 > )
{
int gridRows = axisYModel.Titles.Count - ;
for (int i = ; i < gridRows; i++)
{
LeftGrid.RowDefinitions.Add(new RowDefinition());
MainGridForRow1.RowDefinitions.Add(new RowDefinition());
}
int index = ;
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(, , , -axisYModel.LabelHeight / );//因为设置在行底部还不够,必须往下移
Grid.SetRow(textblock, gridRows - index - );
}
else
{
textblock.VerticalAlignment = VerticalAlignment.Top;
textblock.Margin = new Thickness(, -axisYModel.LabelHeight / , , );//最后一个,设置在顶部
Grid.SetRow(textblock, );
}
LeftGrid.Children.Add(textblock); var border = new Border();
border.Height = axisYModel.LineHeight;
border.BorderBrush = axisYModel.LineBrush;
double thickness = Convert.ToDouble(axisYModel.LineHeight) / ;
border.BorderThickness = new Thickness(, thickness, , thickness);
if (index < gridRows)
{
border.VerticalAlignment = VerticalAlignment.Bottom;
border.Margin = new Thickness(, , , -thickness);//因为设置在行底部还不够,必须往下移
Grid.SetRow(border, gridRows - index - );
}
else
{
border.VerticalAlignment = VerticalAlignment.Top;
border.Margin = new Thickness(, -thickness, , );//最后一个,设置在顶部
Grid.SetRow(border, );
}
Grid.SetColumn(border, );
Grid.SetColumnSpan(border, AxisX.Datas.Count + );
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 = ; 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 - ;
_lastHorizontalOffset = startOffset - ;
}
else if (startOffset > _lastHorizontalOffset)
{
BtnLeft.Opacity = 0.5;
}
BtnRight.Opacity = ;
} private double _lastHorizontalOffset = ;
/// <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 + ;
_lastHorizontalOffset = startOffset + ;
}
else if (startOffset < _lastHorizontalOffset)
{
BtnRight.Opacity = 0.5;
}
BtnLeft.Opacity = ;
}
}
#region XDataModel
public class AxisXModel
{
private double _labelWidth = ;
/// <summary>
/// 底部标签-单个宽度
/// </summary>
public double LabelWidth
{
get { return _labelWidth; }
set { _labelWidth = value; }
}
private double _marginWidth = ;
/// <summary>
/// Bar间隔宽度
/// </summary>
public double MarginWidth
{
get { return _marginWidth; }
set { _marginWidth = value; }
}
private double _height = ;
/// <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 = ;
/// <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 YDataModel
public class AxisYModel
{
private double _width = ;
/// <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 = ;
/// <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
{ }
#endregion public class DataModel
{
/// <summary>
/// 显示名称
/// </summary>
public string Name { get; set; } /// <summary>
/// 值
/// </summary>
public double Value { get; set; }
}
}

界面引用:

<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>

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

WPF 自定义BarChartControl(可左右滑动的柱状图)的更多相关文章

  1. WPF 自定义BarChartControl(可左右滑动的柱状图)(转)

    自定义可左右滑动.拖拽滑动的平面柱状图 在做这种样式控件之前,可先浏览我之前预研的控件: A.自定义左右滑动ScrollViewer(可拖动滑动) B.自定义Bar柱状图 OK,现在说下控件具体设计过 ...

  2. WPF 自定义柱状图 BarChart

    WPF 自定义柱状图 当前的Telerik控件.DevExpress控件在图表控件方面做得不错,但是有时项目中需要特定的样式,不是只通过修改图表的模板和样式就能实现的. 或者说,通过修改当前的第三方控 ...

  3. wpf 自定义圆形按钮

    wpf 自定义圆形按钮 效果图 默认样式 获取焦点样式 点击样式 下面是实现代码: 一个是自定义控件类,一个是控件类皮肤 using System; using System.Collections. ...

  4. WPF自定义窗口基类

    WPF自定义窗口基类时,窗口基类只定义.cs文件,xaml文件不定义.继承自定义窗口的类xaml文件的根节点就不再是<Window>,而是自定义窗口类名(若自定义窗口与继承者不在同一个命名 ...

  5. WPF 自定义 MessageBox (相对完善版)

    WPF 自定义 MessageBox (相对完善版)     基于WPF的自定义 MessageBox. 众所周知WPF界面美观.大多数WPF元素都可以简单的修改其样式,从而达到程序的风格统一.可是当 ...

  6. WPF自定义Window样式(2)

    1. 引言 在上一篇中,介绍了如何建立自定义窗体.接下来,我们需要考虑将该自定义窗体基类放到类库中去,只有放到类库中,我们才能在其他地方去方便的引用该基类. 2. 创建类库 接上一篇的项目,先添加一个 ...

  7. WPF自定义Window样式(1)

    1. 引言 WPF是制作界面的一大利器.最近在做一个项目,用的就是WPF.既然使用了WPF了,那么理所当然的,需要自定义窗体样式.所使用的代码是在网上查到的,遗憾的是,整理完毕后,再找那篇帖子却怎么也 ...

  8. WPF自学入门(九)WPF自定义窗口基类

    今天简单记录一个知识点:WPF自定义窗口基类,常用winform的人知道,winform的窗体继承是很好用的,写一个基础窗体,直接在后台代码改写继承窗体名.但如果是WPF要继承窗体,我个人感觉没有理解 ...

  9. WPF自定义TabControl样式

    WPF自定义TabControl,TabControl美化 XAML代码: <TabControl x:Class="SunCreate.Common.Controls.TabCont ...

随机推荐

  1. Atitit. 破解  拦截 绕过 网站 手机 短信 验证码  方式 v2 attilax 总结

    Atitit. 破解  拦截 绕过 网站 手机 短信 验证码  方式 v2 attilax 总结 1. 验证码的前世今生11.1. 第一代验证码 图片验证码11.2. 第二代验证码  用户操作 ,比如 ...

  2. 基于Caffe的DeepID2实现(上)

    小喵的唠叨话:小喵最近在做人脸识别的工作,打算将汤晓鸥前辈的DeepID,DeepID2等算法进行实验和复现.DeepID的方法最简单,而DeepID2的实现却略微复杂,并且互联网上也没有比较好的资源 ...

  3. js实现StringBuffer

    实现 function StringBuffer() { this.__strings__ = []; }; StringBuffer.prototype.Append = function (str ...

  4. 我为什么要自己编译openjdk8以及那些坑

    我为什么要自己编译openjdk8以及那些坑 这是笔者第二次编译openjdk, 第一次编译的是openjdk7,那么好多人会好奇,为什么要自己编译openjdk呢,官方不是已经发布了安装包了么? 要 ...

  5. 【十大经典数据挖掘算法】EM

    [十大经典数据挖掘算法]系列 C4.5 K-Means SVM Apriori EM PageRank AdaBoost kNN Naïve Bayes CART 1. 极大似然 极大似然(Maxim ...

  6. C# 文件下载之断点续传

    注意,本文所说的断点续传特指 HTTP 协议中的断点续传.本文主要聊聊思路和关键代码,更多细节请参考本文附带的 demo. 工作原理 HTTP 协议中定义了一些请求/响应头,通过组合使用这些头信息.我 ...

  7. C# VLCPlayer视频播放器(附源码)

    VLCPlayer视频播放器. 支持本地播放,支持网络URL.支持全屏,截图. 基于VLCPlayer. 附带基本代码. 下载地址:http://pan.baidu.com/s/1nvjNvID

  8. Both must set "document.domain" to the same value to allow access.

    有两个域名指向我的网站,其中一个域名访问我的网站的话就可以看到日期控件 另一个域名访问我的网站不能看到日期控件, 在EF中使用日期控件,浏览器审查元素后看到,报这个错误“Both must set & ...

  9. 【C#】给无窗口的进程发送消息

    注:本文适用.net2.0+的winform程序 一个winform程序,我希望它不能多开(但是如何防多开不是本文要讲的),那么在用户启动第二个实例的时候,作为第二个实例来说,大概可以有这么几种做法: ...

  10. SimpleSSO:使用Microsoft.Owin.Security.OAuth搭建OAuth2.0授权服务端

    目录 前言 OAuth2.0简介 授权模式 (SimpleSSO示例) 使用Microsoft.Owin.Security.SimpleSSO模拟OpenID认证 通过authorization co ...