http://blog.csdn.net/sanjiawan/article/details/6785394
前几天打算尝试下DataGrid的用法,起初以为应该很简单,可后来被各种使用方法和功能实现所折磨。网络上的解决方法太多,但也太杂。没法子,我只好硬着头皮阅览各种文献资料,然后不断的去尝试,总算小有成果。因此,把我学到的和大家分享一下,相信这篇文章会让你再很短的时间内学会DataGrid的大部分主要功能,而且很多难点都可以在里面找到解决方案。
由于涉及的应用比较多,所以篇幅会很长。但可以确保各个版块相互独立 ,总共4个部分
1.数据绑定
2.DataGrid的增改删功能
3.DataGrid的分页实现
4.DataGrid的样式设计
先上一张截图,让你大概知道自己需要的功能是否在这张图里有所实现。
PS:使用技术:WPF + ADO.NET Entity Framework
1.数据绑定(涉及DataGrid绑定和Combox绑定)
在DataGrid 中同时包含“自动生成列”与“用户自定义列” 由属性AutoGenerateColumns控制。
默认情况下, DataGrid 将根据数据源自动生成列。 下图列出了生成的列类型。
如果AutoGenerateColumns="True" ,我们只需要如下几行代码
后台dataGrid1.ItemsSource = infoList; //infoList为内容集合(这是我从数据库中获取的记录集合 类型为List)
PS:因为这里给dataGrid1绑定了数据源,所以下面绑定的字段都是infoList中的字段名称,同样也对应着我数据表中的字段名。里面包含FID,公司名称,职员姓名,性别,年龄,职务。解释下,怕大家无法理解Binding 后面的值是如何来的了
显然这种数据绑定非常的容易,如果对表格要求不高,这中无疑是最简单方便的。
如果AutoGenerateColumns="False" 表格字段的显示就要靠我们手动去完成了。这个也是数据绑定的重点,因为实际应用中我们大多都是自定义去完成DataGrid的数据绑定。
接下来贴出代码(后面的所有功能都可以在此代码基础上添加和修改 )
< Window x:Class = "CSDN_C.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:assembly = "clr-namespace:System;assembly=mscorlib"
xmlns:local = "clr-namespace:Demo"
Title = "MainWindow" Loaded = "Window_Loaded" >
< Window.Resources >
< ObjectDataProvider x:Key = "keySex" MethodName = "GetValues" ObjectType = "{x:Type assembly:Enum}" >
< ObjectDataProvider.MethodParameters >
< x:Type Type = "local:Sex" > x:Type >
ObjectDataProvider.MethodParameters >
ObjectDataProvider >
Window.Resources >
< Grid >
< DataGrid Name = "dataGrid1" AutoGenerateColumns = "False" >
< DataGrid.Columns >
< DataGridTemplateColumn Header = "操作" Width = "40" >
< DataGridTemplateColumn.CellTemplate >
< DataTemplate >
< CheckBox > CheckBox >
DataTemplate >
DataGridTemplateColumn.CellTemplate >
DataGridTemplateColumn >
< DataGridTextColumn Header = "公司名称" Width = "80" Binding = "{Binding 公司名称, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
< DataGridTextColumn Header = "姓名" Width = "80" Binding = "{Binding 职员姓名, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
< DataGridComboBoxColumn Header = "sex" SelectedItemBinding = "{Binding 性别}" ItemsSource = "{Binding Source={StaticResource keySex}}" />
< DataGridTextColumn Header = "年龄" Width = "80" Binding = "{Binding 年龄, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
< DataGridTextColumn Header = "职务" Width = "80" Binding = "{Binding 职务, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
DataGrid.Columns >
DataGrid >
Grid >
Window >
后台
namespace Demo{
public enum Sex { 男,女 };
}
当我们绑定好数据运行程序的时候,会发现 DataGridComboBoxColumn下拉框里虽然绑定了值,但是他不会默认显示出已经设定好的值。所以我们就可以摈弃这种现有的 DataGridComboBoxColumn,我们用DataGrid样板标签DataGridTemplateColumn 。
我们在DataGridTemplateColumn标签里要用到2个控件,一个 TextBlock控件来显示内容,另一个ComBox来提供选择。
所以我们可以用如下代码替换掉
< DataGridTemplateColumn Header = "性别" >
< DataGridTemplateColumn.CellTemplate >
< DataTemplate >
< TextBlock Text = "{Binding Path=性别}" />
DataTemplate >
DataGridTemplateColumn.CellTemplate >
< DataGridTemplateColumn.CellEditingTemplate >
< DataTemplate >
< ComboBox x:Name = "taskCombo" ItemsSource = "{Binding Source={StaticResource keySex}}" SelectedItem = "{Binding Path=性别}" IsSynchronizedWithCurrentItem = "False" />
DataTemplate >
DataGridTemplateColumn.CellEditingTemplate >
DataGridTemplateColumn >
注意 CellTemplate和 CellEditingTemplate的区别
2.DataGrid的增改删功能
①添加记录行+编辑记录行
由于增加和编辑有一定的联系,所以就放一起来讨论
在上面的代码处添加2个Button按钮,DataGrid默认是输入一行记录后自动会生成一个新行(类似MSSQL数据库添加表记录)。由属性 CanUserAddRows来控制 当 CanUserAddRows=false的时候就不会自动生成新行。为了方便我们自己来控制,所以在DataGrid里面设置CanUserAddRows为false.
< Grid >
< Button Content = "添加" Name = "btnAdd" Click = " btnAdd_Click" />
< Button Content = "保存" Name = "btnSave" Click = "btnSave_Click" />
< DataGrid Name = "dataGrid1" AutoGenerateColumns = "False" CanUserAddRows = "False" >
DataGrid >
Grid >
后台事件
int judge = 0;
TB_Information tbInfo = new TB_Information();
private void btnAdd_Click( object sender, RoutedEventArgs e)
{
judge = 1;
dataGrid1.CanUserAddRows = true ;
}
List lstInformation = new List();
private void dataGrid1_RowEditEnding( object sender, DataGridRowEditEndingEventArgs e)
{
Information info = new Information();
info = e.Row.Item as Information;
if (judge == 1)
{
lstInformation.Add(info);
}
else
{
tbInfo.UpdInformation(info);
}
}
private void btnSave_Click( object sender, RoutedEventArgs e)
{
foreach (Information info in lstInformation)
{
tbInfo.InsInformation(info);
}
judge = 0;
lstInformation.Clear();
dataGrid1.CanUserAddRows = false ;
Binding(Num, 1);
}
这里又会遇到一个问题。那就是更新数据的时候,发现数据更本就没更新。跟踪代码会发现后台得到的值还是原来的,无法获取编辑后的值。这个问题就是绑定模式的问题,我们只需设置双向绑定就可以了。且作用对象是在属性值更改的情况下进行双向绑定。 只要在前面的每个表字段处加上 Mode=TwoWay, UpdateSourceTrigger=PropertyChanged 问题就解决了
例如: Binding="{Binding 公司名称, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
②删除记录
为了有良好的用户体验,我就做了个可以批量删除的删除功能。就是利用到CheckBox控件来完成。
以绑定代码为基础添加代码
首先我们要获取CheckBox中的值,有哪些是被选中的。显然CheckBox里面还必须绑定值,并且还需要一个事件。给CheckBox添加的代码如下
Click="CheckBox_Click" Tag="{Binding FID}" >
后台代码
List<int > selectFID = new List< int >();
private void CheckBox_Click( object sender, RoutedEventArgs e)
{
CheckBox dg = sender as CheckBox;
int FID = int .Parse(dg.Tag.ToString());
var bl = dg.IsChecked;
if (bl == true )
{
selectFID.Add(FID);
}
else
{
selectFID.Remove(FID);
}
}
private void btnDelete_Click( object sender, RoutedEventArgs e)
{
foreach ( int FID in selectFID)
{
tbInfo.DelInformation(FID);
}
}
3.DataGrid的分页实现
原理:其实分页功能的实现大家都清楚,无非就是把一个记录集通过运算来刷选里面对应页码的记录。
接来下我们再次添加新的代码
< Grid >
< DataGrid Name = "dataGrid1" AutoGenerateColumns = "False" >
DataGrid >
< StackPanel Orientation = "Horizontal" >
< TextBlock Text = "转到" Margin = "5" />
< TextBox Name = "tbxPageNum" Text = "" />
< TextBlock Text = "页" />
< Button Content = "GO" Click = "btnGo_Click" />
< Button Name = "btnUp" Content = "上一页" VerticalAlignment = "Center" Click = "btnUp_Click" />
< Button Name = "btnNext" Content = "下一页" VerticalAlignment = "Center" Click = "btnNext_Click" />
< TextBlock Height = "20" >
< TextBlock Text = "【共" />
< TextBlock Name = "tbkTotal" Foreground = "Red" />
< TextBlock Text = "页】" />
< TextBlock Text = "【当前" />
< TextBlock Name = "tbkCurrentsize" Foreground = "Red" />
< TextBlock Text = "页】" />
TextBlock >
StackPanel >
Grid >
首先我们先写个分页的方法,供上面这些事件调用
后台代码
private void Binding( int number, int currentSize)
{
List infoList = new List();
infoList = tbInfo.GetInformationList();
int count = infoList.Count;
int pageSize = 0;
if (count % number == 0)
{
pageSize = count / number;
}
else
{
pageSize = count / number + 1;
}
tbkTotal.Text = pageSize.ToString();
tbkCurrentsize.Text = currentSize.ToString();
infoList = infoList.Take(number * currentSize).Skip(number * (currentSize - 1)).ToList();
dataGrid1.ItemsSource = infoList;
}
const int Num=12;
private void btnUp_Click( object sender, RoutedEventArgs e)
{
int currentsize = int .Parse(tbkCurrentsize.Text);
if (currentsize > 1)
{
Binding(Num, currentsize - 1);
}
}
private void btnNext_Click( object sender, RoutedEventArgs e)
{
int total = int .Parse(tbkTotal.Text);
int currentsize = int .Parse(tbkCurrentsize.Text);
if (currentsize < total)
{
Binding(Num, currentsize + 1);
}
}
private void btnGo_Click( object sender, RoutedEventArgs e)
{
int pageNum = int .Parse(tbxPageNum.Text);
int total = int .Parse(tbkTotal.Text);
if (pageNum >= 1 && pageNum <= total)
{
Binding(Num, pageNum);
}
}
4.DataGrid的样式设计
为什么用WPF,不就是因为WPF拥有绚丽的设计页面功能么(当然远不止这些)。虽然我美工这方面很差劲,但是最基本的设计我们还是要会一些。所以接下来做的工作主要就是给DataGrid上色了。(有些需要用到后台代码,也许不属于样式这类,但总归是改变外观,所以就放在一起归纳了)
①给DataGrid自动添加行序号+修改行表头颜色
后台代码
private void Window_Loaded( object sender, RoutedEventArgs e)
{
Binding(Num, 1);
dataGrid1.LoadingRow += new EventHandler(dataGrid_LoadingRow);
}
public void dataGrid_LoadingRow( object sender, DataGridRowEventArgs e)
{
e.Row.Header = e.Row.GetIndex() + 1;
}
接下来就可以修改行表头的颜色了
< DataGrid Name = "dataGrid1" >
< DataGrid.RowHeaderStyle >
< Style TargetType = "DataGridRowHeader" >
< Setter Property = "Width" Value = "15" />
< Setter Property = "Background" >
< Setter.Value >
< LinearGradientBrush StartPoint = "0,0" EndPoint = "1,1" >
< GradientStop Color = "White" Offset = "0" />
< GradientStop Color = "SkyBlue" Offset = "1" />
LinearGradientBrush >
Setter.Value >
Setter >
Style >
DataGrid.RowHeaderStyle >
DataGrid >
②给列表头添加颜色
< DataGrid Name = "dataGrid1" >
< DataGrid.ColumnHeaderStyle >
< Style TargetType = "DataGridColumnHeader" >
< Setter Property = "Background" >
< Setter.Value >
< LinearGradientBrush StartPoint = "0,0" EndPoint = "0,1" >
< GradientStop Color = "White" Offset = "0" />
< GradientStop Color = "LightBlue" Offset = "0.5" />
< GradientStop Color = "White" Offset = "1" />
LinearGradientBrush >
Setter.Value >
Setter >
< Setter Property = "Foreground" Value = "Black" />
< Setter Property = "FontSize" Value = "13" />
Style >
DataGrid.ColumnHeaderStyle >
< DataGrid.Columns >
< DataGridTemplateColumn Header = "操作" Width = "40" >
< DataGridColumn.HeaderStyle >
< Style TargetType = "DataGridColumnHeader" >
< Setter Property = "Background" >
< Setter.Value >
< LinearGradientBrush StartPoint = "0,0" EndPoint = "0,1" >
< GradientStop Color = "White" Offset = "0" />
< GradientStop Color = "Yellow" Offset = "0.5" />
< GradientStop Color = "White" Offset = "1" />
LinearGradientBrush >
Setter.Value >
Setter >
< Setter Property = "Foreground" Value = "Black" />
< Setter Property = "FontSize" Value = "13" />
< Setter Property = "Width" Value = "70" />
Style >
DataGridColumn.HeaderStyle >
DataGridTemplateColumn >
DataGrid.Columns >
DataGrid >
③给行添加颜色+滑鼠事件
< DataGrid Name = "dataGrid1" >
< DataGrid.RowStyle >
< Style TargetType = "DataGridRow" >
< Setter Property = "Background" Value = "LightBlue" />
< Style.Triggers >
< Trigger Property = "IsMouseOver" Value = "True" >
< Setter Property = "Background" Value = "SkyBlue" />
< Setter Property = "Foreground" Value = "White" />
Trigger >
Style.Triggers >
Style >
DataGrid.RowStyle >
lt;/DataGrid>
④给单元格添加颜色
< DataGrid Name = "dataGrid1" >
< DataGrid.CellStyle >
< Style TargetType = "DataGridCell" >
< Style.Triggers >
< Trigger Property = "IsSelected" Value = "True" >
< Setter Property = "Background" Value = "LightPink" />
Trigger >
Style.Triggers >
Style >
DataGrid.CellStyle >
DataGrid >
⑤ 让用户在单元格获得焦点时编辑 ComboBox
其实这不属于样式的范畴了,但我喜欢把改善用户体验归于这一类。当我们的表格里有类似ComboBox的控件时(如: DatePicker 控件等)。我们编辑这些控件时,首先第一次单击获取单元格焦点,
第二次点击才能获取编辑时的焦点,也就是用户必须单击2次才能进行操作。这种机制其实是适合文本框控件的,但对于其它控件,像ComboBox就显得很不方便了。所以我们要做的就是单击第一次的
时候用户就可以编辑ComboBox。
接下来我要在DataGrid添加了三个新属性(RowDetailsVisibilityMode、SelectionMode 和 SelectionUnit)和一个新的事件处理程序 (SelectedCellsChanged)
前台
RowDetailsVisibilityMode="VisibleWhenSelected" SelectionMode="Extended" SelectionUnit="Cell" SelectedCellsChanged="dataGrid1_SelectedCellsChanged" >
后台
现在就差一个 SelectedCellsChanged(选则单元格时出发该事件)事件的后台代码了
private void dataGrid1_SelectedCellsChanged( object sender, SelectedCellsChangedEventArgs e)
if (e.AddedCells.Count == 0)
return ;
var currentCell = e.AddedCells[0];
if (currentCell.Column == dataGrid1.Columns[3])
{
dataGrid1.BeginEdit();
}
⑥固定列表头
这个非常简单 只要在DataGrid里添加一个属性即可
FrozenColumnCount="1" >
费了不少时间,希望可以帮助大家。有什么地方有误欢迎大家指正!!!