继续我们的Silverlight之路,接下来进入“基金分析”模块。其实这个模块是我最开始做的,所以它包括的内容也更多一些,因为是练习项目,所以有些实现我分别用了不同的方法,真正的项目中可不能这样,呵呵。
本节主要内容:实体框架自定义查询;datagrid大数据量滚动“卡”;datagrid加行序号;
还是先看看整体效果
乍一看上去,与客户管理比较相像,主体也是一个表格。是的,这个表格就是该页面的主要功能部分,但与客户管理中不同的是,因为是行情,所以很自然的,这里不能用分页,否则行情的优势就体现不出来了。也因为是行情,就要求体现出涨跌,比如如果是涨的,就要以红色显示;如果是绿的,就表现跌了,这也符合传统的表现形式。
接下来看看实现步骤吧
按我们的项目结构,还是新建一个项目做为“基金分析”模块,项目中MainPage.xaml做为模块主页,FundQuotes.xaml做为行情页面,主界面还与之前的模块一样,这里主要看行情页面
上面几个列表框,没啥说的,绑定就可以了。表格的数据就有些复杂了,它的数据来源于不同的数据表,而之前我们的模块中使用的均为单一数据表,也就是一个实体对像就可以搞定了,而现在不行了。因为我的项目是在原来web项目的基础上进行的,原来为行情表格提供数据的底层是一个sql server中的表值函数,但在实体框架中是不能使用函数的,如图
只有表,视图与存储过程支持。因此这里我们要使用实体框架提供的另一个方法,即对数据源直接进行查询,然后用查询结果填充一个实体对象,实体对象就只有手动创建了,至少我没有找到合适的方法。代码如下
using (var entities = new DAL.WFT_101104Entities())
{
return entities.ExecuteStoreQuery<Module.FundQuotes>("SELECT * FROM JJGaiKuang (@jjgongsi,@jjtype,@IsOnwerSale,@WorkNo,@BuyState,@bankname,@tzfg)",
new System.Data.SqlClient.SqlParameter("@jjgongsi", jjgongsi),
new System.Data.SqlClient.SqlParameter("@jjtype", jjtype),
new System.Data.SqlClient.SqlParameter("@IsOnwerSale", IsOnwerSale),
new System.Data.SqlClient.SqlParameter("@WorkNo", WorkNo),
new System.Data.SqlClient.SqlParameter("@BuyState", BuyState),
new System.Data.SqlClient.SqlParameter("@bankname", bankname),
new System.Data.SqlClient.SqlParameter("@tzfg", tzfg)).ToList();
}
}
其中的FundQuotes就是我自己创建的实体对象。
这里还有一个办法,使用数据集的形式,它可以直接自定义查询并生成相应的实体,如
但它产生的是一个DataSet,而Silverlight中是不支持使用DataSet与DataTable这样的数据集的(因为它们是弱类型且体积庞大),那我们就需要再给它转换成实体对象,网上有相关的介绍,代码太多,有需要的可以网上找一下“DataTable与实体类互相转换”,我这里只是贴出调用代码
using (var entities = new DAL.WFT_101104Entities())
{
return new Module.EntityConvert<Module.FundQuotes>().FillModel(
new DAL.FundDataSetTableAdapters.JJGaiKuangTableAdapter().GetData(jjgongsi, jjtype, IsOnwerSale, WorkNo, BuyState, bankname, tzfg));
}
但在项目中即使用数据集又使用实体框架,有些不伦不类的感觉,当然,这里只是做个介绍,我使用的是第一种方法。(其实可以利用数据集的方法创建出实体类,当字段比较多时可能会方便一点吧,不过也没感觉方便哪去。。。)
以上就是基金行情数据表的WCF服务端实现,数据已经有了,再回头看看前端吧。
前端表格由于不进行分页处理,因此不像客户管理那样麻烦,数据量几百条也不算大,直接绑定吧,效果是出来了,但滚动时卡的不行,我的实现是在一个ScrollViewer中放置这个表格,想利用ScrollViewer的滚动功能进行表格数据滚动,就像传统的web开发中把一个表格放到一个div中一样,但在sl里看来是不行。后来经过分析,怀疑是因为滚动的时候,表格要进行重绘,而几百条数据都要进行绘制,因此就会卡,虽然它们大部分是看不见的。网上找了一下,发现有网友也有此问题,解决办法就是使用datagrid自己的滚动条,即:HorizontalScrollBarVisibility="Auto",不过在blend里我发现两个一样的属性,不知道是不是blend的bug,还是我没有理解,如
表格的第一列还是一个选择列,开始实现时我使用的是DataGridCheckBoxColumn列,然后把它绑定到一个bool属性(因为实体类是我自己创建的,因此手动加上了一个bool类型的属性用来与选择列绑定),但发现总是不能勾选,原来是因为我设置了表格的IsReadOnly,所以绑定值的勾选列自然也不允许修改了,解决办法是去掉表格的IsReadOnly属性,然后把其它列的IsReadOnly属性设置为true。再试,还有问题,当我想勾选某一行时,总是会先选择该行,再次点击时才会被勾选成功,这。。。太不爽了吧~!找了好半天没发现有啥办法,最后只能继续使用DataGridTemplateColumn了
<sdk:DataGridTemplateColumn Header="选择" >
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding 选择, Mode=TwoWay}" HorizontalAlignment="Center" VerticalAlignment="Center"></CheckBox>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
真不知道DataGridCheckBoxColumn有什么用,还是我没发现它的价值呢?
再看我们的表格,还有一个序列号,这一列要求显示表格的行号,也就是说它不能是数据源提供的,因为不管如何排序,它要求始终显示行号,在sl中的实现有些类似web中的办法,代码如
void gridQuotes_LoadingRow(object sender, DataGridRowEventArgs e)
{
int index = e.Row.GetIndex();
var cell = this.gridQuotes.Columns[1].GetCellContent(e.Row) as TextBlock;
cell.Text = (index + 1).ToString();
}
如果想在行头上加上序号,e.Row.Header = e.Row.GetIndex() + 1;
在简单调整一下表格样式,全是blend的操作,不多说了,以后有机会我再整理一下blend的使用经验吧,敬请期待,呵呵。