DataGrid数据表格控件
DataGrid是一个可以多选的数据表格控件。所以,它继承一个支持多选的父类——MultiSelector。
public abstract class MultiSelector : Selector
{protected MultiSelector();public IList SelectedItems { get; }protected bool CanSelectMultipleItems { get; set; }protected bool IsUpdatingSelectedItems { get; }public void SelectAll();public void UnselectAll();protected void BeginUpdateSelectedItems();protected void EndUpdateSelectedItems();}
从上面的定义来看,DataGrid多选的结果会保存在SelectedItems 只读属性中,CanSelectMultipleItems 属性用来设置是否开启多选。
1. DataGrid属性分析
DataGrid提供了大量的依赖属性,合理充分利用这些属性,在开发ERP、CMS、报表等软件时可达到事半功倍的效果。这里我给大家只列出常用的和重要的,如果有想了解所有属性的,可以参考官网。
- RowHeaderTemplate:获取或设置行标题的模板。(重要)
- CanUserAddRows:是否可以添加新行。 (重要)
- CurrentItem:当前选中行(一般指绑定的数据源的某一个元素。)(常用)
- CanUserDeleteRows:是否可以删除行。 (重要)
- RowHeaderStyle:获取或设置应用于所有行标题的样式。 (重要)
- IsReadOnly:当前控件是否只读。(常用)
- ColumnHeaderStyle:获取或设置所有列标题的样式。 (重要)
- RowStyle:获取或设置应用到的所有行的样式。 (重要)
- AlternatingRowBackground:获取或设置交替行上使用的背景画笔。 (重要)
- VerticalGridLinesBrush:获取或设置用于绘制垂直网格线的画笔。 (常用)
- Columns:获取一个集合中的所有列。 (常用)
- CellStyle:获取或设置所有单元格的样式。 (常用)
- FrozenColumnCount: 获取或设置非滚动列的数量。 (常用)
- AutoGenerateColumns:获取或设置一个值,该值指示是否自动创建列。 (常用)
- CanUserSortColumns:是否可以单击列标题来对列排序。 (常用)
- SelectionMode:是否支持多选 。(重要)
在上述,Columns属性是DataGrid最基本的一个属性。它是一个ObservableCollection<DataGridColumn>
类型的集合,表示DataGrid的列的集合。其实DataGridColumn只是一个抽象基类,我们真正在实例化时,是实例化DataGridColumn的子类,然后放到Columns属性中。
事件成员
- Sorting 对列进行排序时发生。
- AutoGeneratedColumns: 所有列的自动生成完成后发生。
- AutoGeneratingColumn: 自动生成单独的列时出现。
- ColumnHeaderDragDelta:每次鼠标位置发生更改时在用户拖动列标题时发生。
- ColumnHeaderDragStarted: 当用户开始使用鼠标拖动列标题时发生。
- ColumnHeaderDragCompleted: 当用户使用鼠标拖动后释放列标题时发生。
- SelectedCellsChanged: 发生时 DataGrid.SelectedCells 集合更改。
- ColumnReordering:在列移至的显示顺序中的新位置之前发生。
- RowDetailsVisibilityChanged:当某一行的可见性详细信息元素更改时发生。
- UnloadingRow:发生时 DataGridRow 对象将成为可供重用。
- LoadingRowDetails:新的行的详细信息模板应用于行时发生。
- InitializingNewItem:创建一个新项时出现。
- PreparingCellForEdit:在单元格进入编辑模式时发生。
- BeginningEdit:发生行或单元格进入编辑模式之前。
- CurrentCellChanged:在 DataGrid.CurrentCell 属性的值更改后发生。
- CellEditEnding:在单元格的编辑将在提交或取消前发生。
- RowEditEnding:在提交或取消行编辑之前发生。
- LoadingRow: 加载row时。
- ColumnDisplayIndexChanged: 其中一个列更改属性时。
- UnloadingRowDetails:行详细信息元素成为可供重用时发生。
- AddingNewItem: 新项添加到DataGrid之前发生
- CopyingRowClipboardContent: 默认行内容准备好之后发生。
- ColumnReordered: 在列移至的显示顺序中的新位置时发生。
代码示例
前端代码
<Grid><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition Width="200"/></Grid.ColumnDefinitions><DataGrid x:Name="datagrid" SelectionMode="Extended"IsReadOnly="True" SelectionChanged="datagrid_Selected"><DataGrid.Columns><DataGridTextColumn Header="姓名" Binding="{Binding Name}" /><DataGridTextColumn Header="年龄" Binding="{Binding Age}" /><DataGridTextColumn Header="地址" Binding="{Binding Address}" /></DataGrid.Columns></DataGrid><StackPanel Grid.Column="1"><StackPanel Orientation="Horizontal" Margin="5"><TextBlock Text="姓名:"/><TextBlock x:Name="_TextBlockName"/></StackPanel><StackPanel Orientation="Horizontal" Margin="5"><TextBlock Text="年龄:"/><TextBlock x:Name="_TextBlockAge"/></StackPanel><StackPanel Orientation="Horizontal" Margin="5"><TextBlock Text="地址:"/><TextBlock x:Name="_TextBlockAddress"/></StackPanel></StackPanel></Grid>
后端代码
public class Person{public string Name { get; set; }public int Age { get; set; }public string Address { get; set; }}/// <summary>/// MainWindow.xaml 的交互逻辑/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();datagrid.Items.Add(new Person { Name = "张三", Age = 22, Address = "广东省廉江市车板镇大坝村" });datagrid.Items.Add(new Person { Name = "李四", Age = 23, Address = "江西省景德镇市市辖区" });datagrid.Items.Add(new Person { Name = "王五", Age = 24, Address = "上海市虹口区" });}private void datagrid_Selected(object sender, RoutedEventArgs e){DataGrid datagrid = sender as DataGrid;if (datagrid == null) return;var person = datagrid.SelectedItem as Person;if (person == null) return;_TextBlockName.Text = person.Name;_TextBlockAge.Text = person.Age + "岁";_TextBlockAddress.Text = person.Address;}}
在这个例子中,我们尽量还原了与ListView控件一致的功能, 需要注意的是:我们将DataGrid的IsReadOnly="True"
,这是因为我们直接将数据元素一条一条的加入到DataGrid的Items属性中,而Items属性本身是一个只读属性,不支持写入。这样的话,当鼠标双击时会报错。
如果要解决这个问题,这就要用到ItemsControl基类中的ItemsSource数据源属性。
我们需要采用DataGrid另外一种赋值方式——数据源赋值。即把一个集合绑定到该属性上,这样在前端就可以编辑数据源,从而不会引发报错。
后端修改
List<Person> list = new List<Person>();list.Add(new Person { Name = "张三", Age = 22, Address = "广东省廉江市车板镇大坝村" });
list.Add(new Person { Name = "李四", Age = 23, Address = "江西省景德镇市市辖区" });
list.Add(new Person { Name = "王五", Age = 24, Address = "上海市虹口区" });datagrid.ItemsSource = list;
前端修改
AutoGenerateColumns属性设为不可自动创建列。
<DataGrid x:Name="datagrid" SelectionMode="Extended"IsReadOnly="False"AutoGenerateColumns="False"SelectionChanged="datagrid_Selected"><DataGrid.Columns><DataGridTextColumn Header="姓名" Binding="{Binding Name}" /><DataGridTextColumn Header="年龄" Binding="{Binding Age}" /><DataGridTextColumn Header="地址" Binding="{Binding Address}" /></DataGrid.Columns>
</DataGrid>
ComboBox下拉框控件
ComboBox表示带有下拉列表的控件,实际上可以把它看成两个部分组成,一个类似TextBox文本输入框,所以它有一个Text文本属性,用于获取ComboBox框的文本值,另一个是类似ListBox的列表框,用于显示ComboBox绑定的所有数据源。
ComboBox继承于Selector,所以,它只能是单选操作。
属性成员
- ShouldPreserveUserEnteredPrefix:是否保留用户的输入,或者输入替换匹配项。
- IsEditable:是否启用或禁用编辑文本框中文本
- Text:获取或设置当前选定项的文本。
- IsReadOnly:文本内容是否只读
- SelectionBoxItem:获取在选择框中显示的项。
- MaxDropDownHeight:获取或设置一个组合框下拉列表的最大高度。
- SelectionBoxItemStringFormat:指定选择框中文本的显示格式。
- StaysOpenOnEdit:在编辑输入框文本时,希望下拉框保持打开,则为true。
- IsSelectionBoxHighlighted:是否突出显示SelectionBoxItem。
- IsDropDownOpen:是否打开组合框下拉列表。
- SelectionBoxItemTemplate:获取选择框内容的项模板。
ComboBox示例
<Grid><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition Width="200"/></Grid.ColumnDefinitions><StackPanel><ComboBox x:Name="combobox1" IsEditable="True" Height="30" Margin="20,10" TextBoxBase.TextChanged="combobox1_TextChanged"/><ComboBox x:Name="combobox2" StaysOpenOnEdit="True" VerticalAlignment="Top" SelectionChanged="combobox2_SelectionChanged"Height="30" Margin="20,10" DisplayMemberPath="Name"></ComboBox></StackPanel><StackPanel Grid.Column="1"><StackPanel Orientation="Horizontal" Margin="5"><TextBlock Text="电话:"/><TextBlock x:Name="_TextBlockTel"/></StackPanel><StackPanel Orientation="Horizontal" Margin="5"><TextBlock Text="姓名:"/><TextBlock x:Name="_TextBlockName"/></StackPanel><StackPanel Orientation="Horizontal" Margin="5"><TextBlock Text="年龄:"/><TextBlock x:Name="_TextBlockAge"/></StackPanel><StackPanel Orientation="Horizontal" Margin="5"><TextBlock Text="地址:"/><TextBlock x:Name="_TextBlockAddress"/></StackPanel></StackPanel></Grid>
后端代码
namespace WpfTest01
{public class Person{public string Name { get; set; }public int Age { get; set; }public string Address { get; set; }}public partial class MainWindow : Window{ public MainWindow(){InitializeComponent();List<Person> list = new List<Person>();list.Add(new Person { Name = "张三", Age = 22, Address = "广东省廉江市车板镇大坝村" });list.Add(new Person { Name = "李四", Age = 23, Address = "江西省景德镇市市辖区" });list.Add(new Person { Name = "王五", Age = 24, Address = "上海市虹口区" });combobox2.ItemsSource = list;}private void combobox1_TextChanged(object sender, TextChangedEventArgs e){_TextBlockTel.Text = combobox1.Text;}private void combobox2_SelectionChanged(object sender, SelectionChangedEventArgs e){ComboBox combobox = sender as ComboBox;if (combobox == null) return;var person = combobox.SelectedItem as Person;if (person == null) return;_TextBlockName.Text = person.Name;_TextBlockAge.Text = person.Age + "岁";_TextBlockAddress.Text = person.Address;}}
}
我们在xaml中实例化了两个ComboBox,第一个直接当成了TextBox来使用;第二个则绑定了一个数据源,并在Xaml中指定了DisplayMemberPath属性显示Person的Name,最后在后端代码中,依然使用SelectedItem 属性获取当前选中项,转化成Person,以获取实际的选中数据。