SilverLight之路(六)
结束了一个模块的练习,是不是对Silverlight的结构与使用有了一定的了解了呢?不过毕竟“风险测试”这个模块的功能还是太简单了,那接下来我们开始第二个模块的练习吧,进入“客户管理”模块,主要应用DataGrid、DataPager控件,这节主要说一下全选功能的实现。
先看下效果(比较懒了,样式就没再细调,只注重功能的实现了)
模块主体主要就是一个DataGrid与DataPager的结合,在布局方面有一个注意的地方,在最外层我使用了一个Border控件,它有一个CornerRadius属性用来设置Border的圆角弧度,注意它的类型,虽然它可以接收一个数字为参数,但不要以为它就只可以设置四个角为一样的弧度,你也可以这样进行设置
就如我们的效果一样,设置左上与右上两个角为圆弧,左下与右下保持直角不变。
先看下DataGrid与DataPager的简单实现
<sdk:DataGrid x:Name="dgCustomerList" ></sdk:DataGrid>
<sdk:DataPager x:Name="dpCustomerList" PageSize="20" DisplayMode="FirstLastNumeric"/>
后台代码
client.GetCustomerListPagerCompleted += new EventHandler<WcfService.GetCustomerListPagerCompletedEventArgs>(
(s, ex) =>
{
PagedCollectionView pcv = new PagedCollectionView(ex.Result);
this.dgCustomerList.ItemsSource = pcv;
this.dpCustomerList .Source = pcv;
});
没了,就这么简单,MS已经把绑定与分页做到极致傻瓜式了。但往往我们的项目中,这种太过简单的实现是满足不了要求的,就比如一般的数据源中都会有ID标识列,我们这样利用自动生成列的办法显然不行,那我们就麻烦点,手动创建列吧。
<sdk:DataGrid x:Name="dgCustomerList" AutoGenerateColumns="False" >
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Header="客户姓名" Binding="{Binding 客户姓名}"/>
<sdk:DataGridTextColumn Header="证件号码" Binding="{Binding 证件号码}"/>
<sdk:DataGridTextColumn Header="客户类型" Binding="{Binding 客户类别}"/>
<!—模板列-->
<sdk:DataGridTemplateColumn Header="账户分析">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<HyperlinkButton Content="查看" Tag="{Binding FundAccount}" HorizontalAlignment="Center" VerticalAlignment="Center"></HyperlinkButton>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
<!--其它列-->
</sdk:DataGrid.Columns>
</sdk:DataGrid>
这里,如果你有某一列没有指定数据源,例如没有设置Binding,则打开页面时就会出问题,我这里就是白屏了。
一般我们的数据表格会在第一列有一个选择列的存在,以方便对某些行进行选择,我们也是使用模块列来实现(虽然DataGrid自己提供了一个DataGridCheckBoxColumn,但也要绑定数据源,而我们的源数据里是没有一个bool字段用来给它绑定的,因此我觉得用起来比较不方便,就用了模板列)
<sdk:DataGridTemplateColumn HeaderStyle="{StaticResource DataGridColumnHeaderStyle1}" CellTemplate="{StaticResource DataTemplate1}"/>
用列头模块加载一个用来进行全选的CheckBox,单元格模板加载一个CheckBox,资源。。。代码太多了,我就不贴了,都是Blend自动生成的,我只贴关键部分吧
列头模板
<CheckBox x:Name="ckHeader" Content="" Click="CheckBox_Click" HorizontalAlignment="Center" VerticalAlignment="Center"/>
单元格模板
<DataTemplate x:Key="DataTemplate1">
<CheckBox x:Name="ck" Content="" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</DataTemplate>
后台代码
//记录选择行
private ObservableCollection< WcfService.WFT_Batch_CustomerClassification> selectItem = new ObservableCollection< WcfService.WFT_Batch_CustomerClassification>();
private void CheckBox_Click(object sender, System.Windows.RoutedEventArgs e)
{//全选
CheckBox chk = sender as CheckBox;
ckHeader = chk;//记录列头全选按钮引用
bool check = chk.IsChecked.Value;
PagedCollectionView pcv = this.dgCustomerList.ItemsSource as PagedCollectionView;//注意,这里为当前页
if (check)
{
foreach (WcfService.WFT_Batch_CustomerClassification p in pcv)
{
selectItem.Add(p);
chk = this.dgCustomerList.Columns[0].GetCellContent(p) as CheckBox;
if (chk != null)
chk.IsChecked = true;
}
}
else
{
foreach (WcfService.WFT_Batch_CustomerClassification p in pcv)
{
chk = this.dgCustomerList.Columns[0].GetCellContent(p) as CheckBox;
if (chk != null)
chk.IsChecked = false;
}
selectItem.Clear();
}
}
void dgCustomerList_LoadingRow(object sender, DataGridRowEventArgs e)
{
CheckBox chk = (CheckBox)this.dgCustomerList.Columns[0].GetCellContent(e.Row);
chk.Click += new RoutedEventHandler(chk_Click);
WcfService.WFT_Batch_CustomerClassification p = chk.DataContext as WcfService.WFT_Batch_CustomerClassification;
chk.IsChecked = selectItem.Contains(p);
}
void chk_Click(object sender, RoutedEventArgs e)
{
CheckBox chk = sender as CheckBox;
bool check = chk.IsChecked.Value;
WcfService.WFT_Batch_CustomerClassification p = chk.DataContext as WcfService.WFT_Batch_CustomerClassification;
if (check)
{
if (!selectItem.Contains(p))
selectItem.Add(p);
}
else
{
selectItem.Remove(p);
}
}
传统的实现上,当进行分页后,要清掉选择数据
void dpCustomerList_PageIndexChanged(object sender, EventArgs e)
{
selectItem.Clear();
if (ckHeader != null)
ckHeader.IsChecked = false;
}
这个方案里LoadingRow事件比较关键,否则你会发现很奇怪的问题,滚动条滚滚试试,勾选状态没了,呵呵。
另外,如果想锁列,只要设置一下DataGrid的FrozenColumnCount属性就可以了。