WPF之DataGrid--列的前台及后台实现
一、前台实现
在xaml里可以很轻松地实现一个如下图所示的DataGrid
<StackPanel> <ComboBox Width="50" HorizontalAlignment="Left" SelectionChanged="ComboBox_SelectionChanged_1"> <ComboBoxItem Content="全部"></ComboBoxItem> <ComboBoxItem Content="男"></ComboBoxItem> <ComboBoxItem Content="女"></ComboBoxItem> </ComboBox> <DataGrid Name="dataGrid" AutoGenerateColumns="False" CanUserAddRows="False"> <DataGrid.Columns> <DataGridCheckBoxColumn> <DataGridCheckBoxColumn.Header> <CheckBox Click="CheckBox_Click_1"></CheckBox> </DataGridCheckBoxColumn.Header> </DataGridCheckBoxColumn> <DataGridTemplateColumn> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Ellipse Height="10" Width="10" Fill="{Binding FillColor}"></Ellipse> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> <DataGridTextColumn Header="姓名" Width="100" Binding="{Binding Name}"></DataGridTextColumn> <DataGridTemplateColumn Header="性别" Width="100"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <RadioButton Content="男" IsChecked="{Binding IsBoy}" Margin="5"></RadioButton> <RadioButton Content="女" IsChecked="{Binding IsGirl}" Margin="5"></RadioButton> </StackPanel> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> <DataGridTemplateColumn Header="住址" Width="200"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Grid Name="address"> <Grid.ColumnDefinitions> <ColumnDefinition Width="5*"></ColumnDefinition> <ColumnDefinition Width="1*"></ColumnDefinition> </Grid.ColumnDefinitions> <TextBox Text="{Binding Address}" Grid.Column="0"></TextBox> <Button Content="Csl" Grid.Column="1" Click="Button_Click_1" Template="{StaticResource ButtonStyle}"></Button> </Grid> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> <Button Content="修改选中行的姓名" Template="{StaticResource ButtonStyle}" Width="72" Height="23" Click="Button_Click_2"></Button> </StackPanel>
二、几个主要的事件代码
1、CheckBox全选、反选:
/// <summary> /// 全选、反选 /// </summary> /// <param name="value"></param> private void ChangeIsChecked(bool value) { for (int i = 0; i < this.dataGrid.Items.Count; i++) { DataGridRow row = (DataGridRow)this.dataGrid.ItemContainerGenerator.ContainerFromIndex(i); if (row != null) { FrameworkElement fe = this.dataGrid.Columns[0].GetCellContent(row); if (fe != null) { CheckBox chk = fe as CheckBox; if (chk.IsChecked.Value == !value) { chk.IsChecked = value; } } } } }
2、ComboBox筛选:
private ICollectionView view; /// <summary> /// 筛选 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ComboBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e) { this.view = CollectionViewSource.GetDefaultView(this.students); switch ((sender as ComboBox).SelectedIndex) { case 0: this.view.Filter = x => true; break; case 1: this.view.Filter = x => (x as Student).IsBoy; break; case 2: this.view.Filter = x => (x as Student).IsGirl; break; default: break; } }
3、修改单元格内容:
private void Button_Click_1(object sender, RoutedEventArgs e) { //获取指定的列 DataGridTemplateColumn column = this.dataGrid.Columns[4] as DataGridTemplateColumn; //获取指定的行与列相交位置的单元格 FrameworkElement element = column.GetCellContent(this.dataGrid.Items[this.dataGrid.SelectedIndex]); Grid grid = column.CellTemplate.FindName("address", element) as Grid; if (grid != null) { TextBox textBox = grid.Children[0] as TextBox; MessageBox.Show(textBox.Text); } }
三、后台实现
一般用于动态生成Column,其实现过程相对要复杂一些。如果某一列在其单元格中承载的是模板,那么其创建的流程为:
1、创建模板FrameworkElementFactory;
2、设置模板的依赖项属性及数据绑定,添加子项;
3、把模板赋给DataTemplate.VisualTree;
4、把DataTemplate赋给DataGridTemplateColumn.CellTemplate;
5、把DataGridTemplateColumn添加到DataGrid.Columns
/// <summary> /// 生成地址列 /// </summary> private void CreateColumnAddress() { DataGridTemplateColumn column = new DataGridTemplateColumn() { Header = "住址", Width = 200.0 }; DataTemplate temp = new DataTemplate(); //生成Grid FrameworkElementFactory grid = new FrameworkElementFactory(typeof(Grid)); grid.Name = "address"; //生成ColumnDefinition FrameworkElementFactory c1 = new FrameworkElementFactory(typeof(ColumnDefinition)); FrameworkElementFactory c2 = new FrameworkElementFactory(typeof(ColumnDefinition)); c1.SetValue(ColumnDefinition.WidthProperty, new GridLength(5, GridUnitType.Star)); c2.SetValue(ColumnDefinition.WidthProperty, new GridLength(1, GridUnitType.Star)); grid.AppendChild(c1); grid.AppendChild(c2); //生成TextBox FrameworkElementFactory textBox = new FrameworkElementFactory(typeof(TextBox)); Binding binding = new Binding("Address"); textBox.SetBinding(TextBox.TextProperty, binding); textBox.SetValue(Grid.ColumnProperty, 0); //生成Button FrameworkElementFactory button = new FrameworkElementFactory(typeof(Button)); button.SetValue(Button.ContentProperty, "Cls"); button.SetValue(Grid.ColumnProperty, 1); button.SetValue(Button.TemplateProperty, this.FindResource("ButtonStyle")); button.AddHandler(Button.ClickEvent, new RoutedEventHandler(Button_Click_1)); grid.AppendChild(textBox); grid.AppendChild(button); temp.VisualTree = grid; column.CellTemplate = temp; this.dataGrid.Columns.Add(column); }
四、源码