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);
        }

四、源码

DataGrid示例

posted @ 2015-08-13 15:48  sunny906  阅读(16841)  评论(2编辑  收藏  举报