a.解决问题--ChartControl不等距x轴显示【图a-1】
b.xaml代码
c.cs代码
d.convert代码
------------------------------a. step start----------------------------------
【图a-1】
用过ChartControl的开发者们应该都知道,ChartControl中设置x轴间距间隔都是固定的数值。
比如(间隔1000)数值为:
0 1000 2000 3000 4000
1 <dxc:AxisY2D.WholeRange>
2 <dxc:Range
3 MaxValue="0"
4 MinValue="4000"
5 SideMarginsValue="0" />
6 </dxc:AxisY2D.WholeRange>
但是,当ChartControl中的某一条数值很小例如值为3,如果不转换的话几乎在控件中看不到用户体验非常不好,解决方案就是实现不等距x轴来显示。
间隔数值可以按照自己的想法来,本文章的数值为:
0 10 100 1000 4000
如果数值设置为不等距,当ChartControl中的某一条数值很小例如值为3的时候,这时候3的数值就可以在0到10这个区间完美显示如图【图a-1】
理想是美好的,那么问题来了,控件实际的间距是固定值1000 而显示间距是0到10这时候怎么转换有人会想0到10的这个域中的值乘以100不就可以满足情况了吗。
是的,这样做可以。但是这个做法非常不科学,因为后面的三个域中的值倍数就不能这么算了。
这时候怎么解决呢?需要用到高中的数学知识分段函数。
公式如下:
附加值:(总长度*当前段数 / 段数)
((实际值 - 域下限) / (域上限 - 域下限))*(总长度 / 段数)+ 附加值
到这里为止,可能只能大概知道这个公式是个什么情况,但是还是不知道具体为什么要这么算。我们接下来在代码中深入了解。
------------------------------b. step start----------------------------------
1.修改ChartControl x轴的显示数值(转换)
1 <local:UpAndDownLabelConverter x:Key="xconv" />
1 <DataTemplate x:Key="AxisYLabelTemplate">
2 <ContentPresenter Content="{Binding Path=Content, Converter={StaticResource xconv}}" />
3 </DataTemplate>
<dxc:AxisY2D.Label>
<dxc:AxisLabel
ElementTemplate="{StaticResource AxisYLabelTemplate}"
Visibility="Visible"
Visible="True">
<dxc:Axis2D.ResolveOverlappingOptions>
<dxc:AxisLabelResolveOverlappingOptions AllowHide="False" />
</dxc:Axis2D.ResolveOverlappingOptions>
</dxc:AxisLabel>
</dxc:AxisY2D.Label>
------------------------------c. step start----------------------------------
/// <summary>
/// 推算出显示值
/// </summary>
/// <param name="xValue">X轴数值</param>
/// <param name="minRange">域下限</param>
/// <param name="maxRange">域上限</param>
/// <param name="totalLength">总长度</param>
/// <param name="period">分了几段</param>
/// <returns></returns>
private static double RangeCalculate(double xValue, double minRange, double maxRange,double totalLength = 4000.0,int period = 4)
{
//实际值 需要转化的实际值
//域上限 0-10 ,10为上限
//域下限 0-10 ,0为下限
//总长度=X轴的上限。例:0 10 100 1000 4000,4000为总长度
//段数:分了几段 例:0-10,10-100,100-1000,1000-4000 分为4段
//当前段数:0-10 第1段 , 10-100 第2段 , 100-1000第3段 ,1000-4000第4段
//段附加值:(总长度 * 当前段数 / 段数) ps:第一段,段附加值为0。附加值是为了值平均
//分段函数公式:((实际值 - 域下限) / (域上限 - 域下限))*(总长度 / 段数)+ 段附加值
double x = 0.0;
if (0 < xValue && xValue <= 10)
{
x = ((xValue - minRange) / (maxRange - minRange)) * (totalLength / period) + 0;
}
if (10 < xValue && xValue <= 100)
{
x = ((xValue - minRange) / (maxRange - minRange)) * (totalLength / period) + (totalLength * 1 / period);
}
if (100 < xValue && xValue <= 1000)
{
x = ((xValue - minRange) / (maxRange - minRange)) * (totalLength / period) + (totalLength * 2 / period);
}
if (1000 < xValue && xValue <= 4000)
{
x = ((xValue - minRange) / (maxRange - minRange)) * (totalLength / period) + (totalLength * 3 / period);
}
return x;
}
------------------------------d. step start----------------------------------
1 public class NotEquidistantLabelConverter : IValueConverter
2 {
3 public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
4 {
5 int target = 0;
6
7 int.TryParse(value.ToString(), out target);
8
9 if (target <= 10)
10 return 0;
11 else if (target <= 1000)
12 return 10;
13 else if (target <= 2000)
14 return 100;
15 else if (target <= 3000)
16 return 1000;
17 else if (target <= 4000)
18 return 4000;
19 return string.Empty;
20 }
21
22 public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
23 {
24 throw new NotImplementedException();
25 }
26 }
如果有任何不妥地方欢迎指出,马上修改。