有了上一篇中的测试结果,我们应该对结果进行一定处理吧,比如列个表,画个图,做个结论啥的,不然做了测试有个毛用啊,呵呵。
我们这个应用的测试结果就是用来绘了两张图,一个判断是属于哪种风险类型,另一个则是根据类型给出推荐配置。
我们这个页面没有太多的细节了(懒的做了,呵呵),只有两个chart控件,如图
关于chart的使用,网上也有很多资料,不过好像都是3.0版本以前的,有些实现方式已经有了很大的变化,不过还好基础是没变的,这里也没太多可说的,可以参考Tookiet的demo,它提供了很多实用的控件,有兴趣可以挨个看一下。
因为sl里的实现多是基于数据绑定的,图表控件也一样,自定义的数据类型如
public class RIResult
{
public string 类型{ get; set; }
public int 值 { get; set; }
}
接下来要做的就是构造这些数据,然后进行绑定,如
饼图实现
void BindPieChart()
{
List<RIResult> result = new List<RIResult>();
result.Add(new RIResult { 类型= "偏股型", 值= 50 });
result.Add(new RIResult { 类型 = "债券型", 值 = 35 });
result.Add(new RIResult { 类型 = "货币型", 值 = 15 });
PieSeries ps = this.chart2.Series[0] as PieSeries;
ps.ItemsSource = result;
ps.DependentValueBinding = new System.Windows.Data.Binding("值");
ps.IndependentValueBinding = new System.Windows.Data.Binding("类型");
}
柱图实现
void BindBarChart()
{
List<RIResult> result = new List<RIResult>();
result.Add(new RIResult { 类型 = "自我认知", 值= 77 });
if (result != null)
{
this.chart1.Title = "风险测试";
//这里预留一个位置,后面我们要在这里加一些内容
BarSeries areaSeries1 = new BarSeries();
areaSeries1.ItemsSource = result;
areaSeries1.IndependentValueBinding = new System.Windows.Data.Binding("类型");
areaSeries1.DependentValueBinding = new System.Windows.Data.Binding("值");
this.chart1.Series.Add(areaSeries1);
}
}
两个实现非常相似,只不过柱图我是用代码创建了一个Series,饼图是用xaml里创建的,效果一样。这里除了PieSeries和BarSeries之外,这套Chart控件还提供了其它很多类型的Series,甚至可以自己实现想要的Series,只要继承基接口并实现就可以了。
这里的Series就是数据充列,为Chart的关键,其它的组成部件如下(这张图是网上找的Visifire Chart的,它也是基于Silverlight Chart的,因此,结构类似)
这有一篇关于Chart控件的说明,可以用来参考
Silverlight的DataVisualization类组件研究(图表控件)
http://hi.baidu.com/ctrlhuhu/blog/item/dd1785134a4aebdef6039e13.html
再回头看一下柱图
注意我画红框的地方,这里是用来标明哪种类型对应哪个区间的描述,根据我目前对Chart控件的理解,这一部分我认为它可以用XAxis.Title来实现,那么,如果对齐位置呢?
于是我想到,既然Title是一个object,也就是说它也可以是我们的控件,那么,一个grid,然后设置5列平均大小就可以达到要求了,那就动手试试吧。
在上面我加注释那一行处加入如下代码(我是代码实现的,应该也可以用样式来做)
Action<Chart> chartModifier = (chart) =>
{
LinearAxis XAxis = this.chart1.Axes[0] as LinearAxis;
XAxis.Minimum = 0;
XAxis.Maximum = 100;
XAxis.Interval = 20;
XAxis.ShowGridLines = true;
XAxis.Orientation = AxisOrientation.X;
Grid xg = new Grid();
xg.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
xg.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
ColumnDefinition cdf1 = new ColumnDefinition();
cdf1.Width = new GridLength(20, GridUnitType.Star);
ColumnDefinition cdf2 = new ColumnDefinition();
cdf2.Width = new GridLength(20, GridUnitType.Star);
ColumnDefinition cdf3 = new ColumnDefinition();
cdf3.Width = new GridLength(20, GridUnitType.Star);
ColumnDefinition cdf4 = new ColumnDefinition();
cdf4.Width = new GridLength(20, GridUnitType.Star);
ColumnDefinition cdf5 = new ColumnDefinition();
cdf5.Width = new GridLength(20, GridUnitType.Star);
xg.ColumnDefinitions.Add(cdf1);
xg.ColumnDefinitions.Add(cdf2);
xg.ColumnDefinitions.Add(cdf3);
xg.ColumnDefinitions.Add(cdf4);
xg.ColumnDefinitions.Add(cdf5);
TextBlock tb1 = new TextBlock();
tb1.Text = "保守型";
tb1.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
TextBlock tb2 = new TextBlock();
tb2.Text = "防御型";
tb2.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
TextBlock tb3 = new TextBlock();
tb3.Text = "稳健型";
tb3.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
TextBlock tb4 = new TextBlock();
tb4.Text = "积极型";
tb4.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
TextBlock tb5 = new TextBlock();
tb5.Text = "进取型";
tb5.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
xg.Children.Add(tb1);
xg.Children.Add(tb2);
xg.Children.Add(tb3);
xg.Children.Add(tb4);
xg.Children.Add(tb5);
Grid.SetColumn(tb1, 0);
Grid.SetColumn(tb2, 1);
Grid.SetColumn(tb3, 2);
Grid.SetColumn(tb4, 3);
Grid.SetColumn(tb5, 4);
XAxis.Title = xg;
};
chartModifier(this.chart1);
这样做了之后,我无论如何不能把grid拉成相要的大小,即使我设置了HorizontalAlignment,它也一直在中间位置不动,气死。。。
不过既然要这里我找不到解决办法,那我绕过去,我用Load事件来做
xg.Loaded += new RoutedEventHandler(sp_Loaded);
然后
void sp_Loaded(object sender, RoutedEventArgs e)
{
((Grid)sender).Width = ((LinearAxis)this.chart1.Axes[0]).ActualWidth;
}
哈哈,这样就搞定了!
这里说明一下ActualWidth,它是显示宽度,但如果你想在它未显示之前取到值是不可能的,之前我有好多处想要用它来进行大小控制,但无奈都取不到正确的值,这里之所以能取到,怀疑是因为在Grid的Load时,它的所属Chart已经显示了的原因。