SilverLight之路(五)

有了上一篇中的测试结果,我们应该对结果进行一定处理吧,比如列个表,画个图,做个结论啥的,不然做了测试有个毛用啊,呵呵。

我们这个应用的测试结果就是用来绘了两张图,一个判断是属于哪种风险类型,另一个则是根据类型给出推荐配置。

我们这个页面没有太多的细节了(懒的做了,呵呵),只有两个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已经显示了的原因。

原文地址:https://www.cnblogs.com/meteortent/p/2079616.html