WPF DataGrid 控件的运用
WPF DataGrid 控件的运用
运行环境:Window7 64bit,.NetFramework4.61,C# 6.0; 编者:乌龙哈里 2017-02-23
参考:
章节:
- 添加列和数据源
- 选择单位设置
- 自动添加行号
- Enter 键做成 Tab 键的效果
- 同步更新数据源
- 在选中 Cell 所在行上插入新行或删除选中 Cell 的所在行
- 获取选中单元格的值
正文:
一、添加列和数据源:
我们往一个 DataGrid 中添加数据源 List< int[] >,注意要在 XAML 代码中把自动添加列的属性给设成 False, AutoGenerateColumns="False" 。
示例1:
C# 代码片段:
List<int[]> list = new List<int[]>();
list.Add(new int[] { 1, 2, 3, 4, 5 });
list.Add(new int[] { 2, 3, 4, 5, 6 });
list.Add(new int[] { 3, 4, 5, 6, 7 });
int _col = list[0].Length;
int _row = list.Count;
for (int i = 0; i < _col; i++)
{
dtgShow.Columns.Add(new DataGridTextColumn
{
Width = (Width - 30) / _col,
Header = $"{(char)(65+i)}",
Binding=new Binding($"[{i.ToString()}]")
});
}
dtgShow.ItemsSource = list;
前端 XAML 片段:
<DataGrid Name="dtgShow" AutoGenerateColumns="False" Margin="3" Grid.Row="0" Grid.ColumnSpan="2"/>
二、选择单位设置:
DataGrid 的选择单位有3种,整行、单个 Cell 、单个 Cell 和 点行头选择整行。DataGrid 缺省状态是整行。我喜欢用第3种。
示例2:
C# 代码片段:
private void GetComboBoxSource()
{
//cbbSelectMode 为 ComboBox 控件实例
cbbSelectMode.Items.Add(DataGridSelectionUnit.Cell);
cbbSelectMode.Items.Add(DataGridSelectionUnit.FullRow);
cbbSelectMode.Items.Add(DataGridSelectionUnit.CellOrRowHeader);
}
private void cbbSelectMode_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
dtgShow.SelectionUnit = (DataGridSelectionUnit)cbbSelectMode.SelectedValue;
}
前端 Xaml 片段:
<ComboBox Name="cbbSelectMode" Margin="2" SelectionChanged="cbbSelectMode_SelectionChanged"/>
运行结果如图:
三、自动添加行号:
直接在 DataGrid 的 LoadingRow() 事件中写:
示例3:
C# 代码片段:
private void dtgShow_LoadingRow(object sender, DataGridRowEventArgs e)
{
e.Row.Header = e.Row.GetIndex() + 1;
}
四、Enter 键做成 Tab 键的效果:
当 DataGrid 选择单位不是 FullRow 时,Enter 键后选择是下一行的 Cell,而选择下一个 Cell 用的是 Tab 键,对输入带来很大的不便。上面的参考中,流泉飞石的写法很简单(要把 KeyDown 事件换成 PreviewKeyDown),但不完美,显示效果不好,原先鼠标选择的蓝色方块并不会跟随回车键跳到下一个 Cell 上,要左右箭头动了才会动。Stackoverflow 论坛上有个 Using Enter Key as Tab in WPF DataGrid,但选择项为 FullRow 时会出错,进入 Cell 的编辑状态回车就跳不出来了。看来还是流泉飞石的好。暂时先这样用了,以后再找更完美的。
示例4:
//Enter 达到 Tab 的效果
private void dtgShow_PreviewKeyDown(object sender, KeyEventArgs e)
{
var uie = e.OriginalSource as UIElement;
if (e.Key == Key.Enter)
{
uie.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
e.Handled = true;
}
}
运行效果图,后面蓝色方块动是我左右键输入才动的:
五、同步更新数据源:
如果 DataGrid 里面的数据更新了,数据源数据也同步更新,最简单的做法就是用 ObservableCollection<T> 类,记得要在前面 using System.Collections.ObjectModel; 要不要手工写通知的程序,有点麻烦。不多说了,上示例:
示例5:
C#代码片段:
List<int[]> list = new List<int[]>();
ObservableCollection<int[]> showdata = new ObservableCollection<int[]>();
//---原始数据源到显示数据源
private void GetShowData()
{
showdata.Clear();
foreach (var a in list)
{
showdata.Add(a);
}
dtgShow.ItemsSource = showdata;
}
//---显示数据到原始数据
private void GetRawData()
{
list.Clear();
foreach (var a in showdata)
{
list.Add(a);
}
}
//---给lbxData(ListBox) 添加数据
private void GetListBoxSource()
{
lbxData.Items.Clear();
StringBuilder sb = new StringBuilder();
foreach (var a in list)
{
sb.Clear();
foreach (var b in a)
{
sb.Append(b.ToString());
sb.Append(" ");
}
lbxData.Items.Add(sb.ToString());
}
}
//---切换 DataGrid 和 ListBox
private void chkResult_Click(object sender, RoutedEventArgs e)
{
CheckBox chk = (CheckBox)sender;
if (chk.IsChecked==true)
{
dtgShow.Visibility = Visibility.Hidden;
lbxData.Visibility = Visibility.Visible;
GetRawData();
GetListBoxSource();
}
else
{
lbxData.Visibility = Visibility.Hidden;
dtgShow.Visibility = Visibility.Visible;
GetShowData();
}
}
Xaml 代码片段:
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="24"/>
<RowDefinition Height="5*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<CheckBox Name="chkResult" Content="查看数据" Margin="3" Grid.Row="0" Grid.Column="1" Click="chkResult_Click" />
<ListBox Name="lbxData" Visibility="Hidden" Grid.Row="1" Grid.ColumnSpan="2"/>
<ComboBox Name="cbbSelectMode" Margin="2" SelectionChanged="cbbSelectMode_SelectionChanged"/>
<DataGrid Name="dtgShow" AutoGenerateColumns="False" Margin="3" Grid.Row="1" Grid.ColumnSpan="2" LoadingRow="dtgShow_LoadingRow" PreviewKeyDown="dtgShow_PreviewKeyDown" />
<Button Content="Add" Margin="3" Grid.Row="2" Grid.Column="0"/>
<Button Content="Remove" Margin="3" Grid.Row="2" Grid.Column="1"/>
</Grid>
六、在选中 Cell 的所在行上插入新行或删除选中的 Cell 所在行:
要解决这个主要就是找到所选 Cell 的行列序号,直接上程序:
示例6:
//增加新行
private void btnAppend_Click(object sender, RoutedEventArgs e)
{
showdata.Add(new int[dtgShow.Columns.Count]);
}
//删除末行
private void btnRemoveLast_Click(object sender, RoutedEventArgs e)
{
if (showdata.Count > 0)
{
showdata.RemoveAt(showdata.Count - 1);
}
}
//---取得选中 Cell 所在的行列
private bool GetCellXY(DataGrid dg, ref int rowIndex, ref int columnIndex)
{
var _cells = dg.SelectedCells;
if (_cells.Any())
{
rowIndex = dg.Items.IndexOf(_cells.First().Item);
columnIndex = _cells.First().Column.DisplayIndex;
return true;
}
return false;
}
//在选中 Cell 所在行上插入新行
private void btnInsert_Click(object sender, RoutedEventArgs e)
{
int _rowIndex = 0;
int _columnIndex = 0;
if(GetCellXY(dtgShow,ref _rowIndex,ref _columnIndex))
{
showdata.Insert(_rowIndex, new int[dtgShow.Columns.Count]);
}
}
//删除选中 Cell 所在行
private void btnRemoveSelect_Click(object sender, RoutedEventArgs e)
{
int _rowIndex = 0;
int _columnIndex = 0;
if (GetCellXY(dtgShow, ref _rowIndex, ref _columnIndex))
{
showdata.RemoveAt(_rowIndex);
}
}
七、获取选中单元格的值
方法一:在上面的示例6中知道了 Cell 的行列,通过 DataGrid 的绑定数据源取得数据;
方法二:DataGrid 每个单元格都是一个 TextBlock 控件,只要取得 TextBlock.Text 就能得到它的 String 值。
下面示例中,我们只需要显示数据,并不需要处理,所以选择方法二来运作。
示例7:
//---获取所有的选中cell 的值
private string GetSelectedCellsValue(DataGrid dg)
{
var cells = dg.SelectedCells;
StringBuilder sb = new StringBuilder();
if (cells.Any())
{
foreach(var cell in cells)
{
sb.Append((cell.Column.GetCellContent(cell.Item) as TextBlock).Text);
sb.Append(" ");
}
}
return sb.ToString();
}
//---显示选中单元格的值
private void dtgShow_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
{
tbxSelect.Text = GetSelectedCellsValue(dtgShow);
}
到此为止,DataGrid 的基本功能基本上摸得七七八八了,哦,还有一个功能是点击列的标题,DataGrid 会自动排序,不用自己实现了,真方便。剩下的像 样式之类的涉及到控件的 DataTemplate 之类的就另外开篇了。这篇也太长了。
下面附上全部的代码:
Xaml 代码:
<Window x:Class="学习WpfDataGrid1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="250">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="24"/>
<RowDefinition Height="5*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<CheckBox Name="chkResult" Content="查看数据" Margin="3" Grid.Row="0" Grid.Column="1" Click="chkResult_Click" />
<ListBox Name="lbxData" Visibility="Hidden" Grid.Row="1" Grid.ColumnSpan="2"/>
<ComboBox Name="cbbSelectMode" Margin="2" SelectionChanged="cbbSelectMode_SelectionChanged"/>
<DataGrid Name="dtgShow" AutoGenerateColumns="False" Margin="3" Grid.Row="1" Grid.ColumnSpan="2" LoadingRow="dtgShow_LoadingRow" PreviewKeyDown="dtgShow_PreviewKeyDown" SelectedCellsChanged="dtgShow_SelectedCellsChanged" />
<TextBox Name="tbxSelect" Grid.Row="2" Grid.ColumnSpan="2"/>
<Button Name="btnAppend" Content="Append" Margin="3" Grid.Row="3" Grid.Column="0" Click="btnAppend_Click" />
<Button Name="btnRemoveLast" Content="Remove Last" Margin="3" Grid.Row="3" Grid.Column="1" Click="btnRemoveLast_Click"/>
<Button Name="btnInsert" Content="Insert" Margin="3" Grid.Row="4" Grid.Column="0" Click="btnInsert_Click" />
<Button Name="btnRemoveSelect" Content="Remove Selected" Margin="3" Grid.Row="4" Grid.Column="1" Click="btnRemoveSelect_Click" />
</Grid>
</Window>
C# 代码:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input; namespace 学习WpfDataGrid1
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
List<int[]> list = new List<int[]>();
ObservableCollection<int[]> showdata = new ObservableCollection<int[]>(); public MainWindow()
{
InitializeComponent();
AddSource();
GetComboBoxSource();
GetShowData();
}
//---原始数据源到显示数据源
private void GetShowData()
{
showdata.Clear();
foreach (var a in list)
{
showdata.Add(a);
}
dtgShow.ItemsSource = showdata;
}
//---显示数据到原始数据
private void GetRawData()
{
list.Clear();
foreach (var a in showdata)
{
list.Add(a);
}
}
//---添加 ComboBox 数据源
private void GetComboBoxSource()
{
//cbbSelectMode 为 ComboBox 控件实例
cbbSelectMode.Items.Add(DataGridSelectionUnit.Cell);
cbbSelectMode.Items.Add(DataGridSelectionUnit.FullRow);
cbbSelectMode.Items.Add(DataGridSelectionUnit.CellOrRowHeader);
cbbSelectMode.SelectedIndex = ; }
//---DataGrid 选择方式
private void cbbSelectMode_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
dtgShow.SelectionUnit = (DataGridSelectionUnit)cbbSelectMode.SelectedValue;
}
//---添加 DataGrid 数据源
private void AddSource()
{
list.Add(new int[] { , , , , });
list.Add(new int[] { , , , , });
list.Add(new int[] { , , , , }); int _col = list[].Length;
//int _row = list.Count;
for (int i = ; i < _col; i++)
{
dtgShow.Columns.Add(new DataGridTextColumn
{
Width = (Width - ) / _col,
Header = $"{(char)(65 + i)}",
Binding = new Binding($"[{i.ToString()}]")
});
}
}
//---自动添加行号
private void dtgShow_LoadingRow(object sender, DataGridRowEventArgs e)
{
e.Row.Header = e.Row.GetIndex() + ;
}
//---Enter 达到 Tab 的效果
private void dtgShow_PreviewKeyDown(object sender, KeyEventArgs e)
{
var uie = e.OriginalSource as UIElement;
if (e.Key == Key.Enter)
{
uie.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
e.Handled = true;
}
}
//---给lbxData(ListBox) 添加数据
private void GetListBoxSource()
{
lbxData.Items.Clear();
StringBuilder sb = new StringBuilder();
foreach (var a in list)
{
sb.Clear();
foreach (var b in a)
{
sb.Append(b.ToString());
sb.Append(" ");
}
lbxData.Items.Add(sb.ToString());
}
}
//---切换 DataGrid 和 ListBox
private void chkResult_Click(object sender, RoutedEventArgs e)
{
CheckBox chk = (CheckBox)sender;
if (chk.IsChecked == true)
{
dtgShow.Visibility = Visibility.Hidden;
lbxData.Visibility = Visibility.Visible;
GetRawData();
GetListBoxSource();
}
else
{
lbxData.Visibility = Visibility.Hidden;
dtgShow.Visibility = Visibility.Visible;
GetShowData();
}
}
//增加新行
private void btnAppend_Click(object sender, RoutedEventArgs e)
{
showdata.Add(new int[dtgShow.Columns.Count]);
}
//删除末行
private void btnRemoveLast_Click(object sender, RoutedEventArgs e)
{
if (showdata.Count > )
{
showdata.RemoveAt(showdata.Count - );
}
}
//---取得选中 Cell 所在的行列
private bool GetCellXY(DataGrid dg, ref int rowIndex, ref int columnIndex)
{
var _cells = dg.SelectedCells;
if (_cells.Any())
{
rowIndex = dg.Items.IndexOf(_cells.First().Item);
columnIndex = _cells.First().Column.DisplayIndex;
return true;
}
return false;
}
//在选中 Cell 所在行上插入新行
private void btnInsert_Click(object sender, RoutedEventArgs e)
{
int _rowIndex = ;
int _columnIndex = ;
if (GetCellXY(dtgShow, ref _rowIndex, ref _columnIndex))
{
showdata.Insert(_rowIndex, new int[dtgShow.Columns.Count]);
}
}
//删除选中 Cell 所在行
private void btnRemoveSelect_Click(object sender, RoutedEventArgs e)
{
int _rowIndex = ;
int _columnIndex = ;
if (GetCellXY(dtgShow, ref _rowIndex, ref _columnIndex))
{
showdata.RemoveAt(_rowIndex);
}
}
//---获取所有的选中cell 的值
private string GetSelectedCellsValue(DataGrid dg)
{
var cells = dg.SelectedCells;
StringBuilder sb = new StringBuilder();
if (cells.Any())
{
foreach(var cell in cells)
{
sb.Append((cell.Column.GetCellContent(cell.Item) as TextBlock).Text);
sb.Append(" ");
}
}
return sb.ToString();
}
//---显示选中单元格的值
private void dtgShow_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
{
tbxSelect.Text = GetSelectedCellsValue(dtgShow);
}
}
}
WPF DataGrid 控件的运用的更多相关文章
- C# WPF DataGrid控件实现三级联动
利用DataGrid控件实现联动的功能,在数据库客户软件中是随处可见的,然而网上的资料却是少之又少,令人崩溃. 本篇博文将介绍利用DataGrid控件模板定义的三个ComboBox实现“省.市.区”的 ...
- NPOI导出WPF DataGrid控件显示数据
最近做个项目,需要导出DataGrid显示的数据,中间遇到了不少的坑,在此纪录一下,方便以后查看,也希望能给用到的人,一点帮助. 导出DataGrid显示的数据,并不是导出DataGrid的Items ...
- WPF DataGrid控件中某一列根据另一个文本列的值显示相应的模板控件
之前做项目的时候需要实现这样一个功能.WPF DataGrid有两列,一列为"更新状态”列,一列为"值"列,如果"更新状态"列的值为“固定值更新”,则 ...
- WPF:获取DataGrid控件单元格DataGridCell
转载:http://blog.csdn.net/jhqin/article/details/7645357 /* ------------------------------------------- ...
- wpf研究之道-datagrid控件(1)
"想要说些什么 又不知从何说起",每当想要写一些关于wpf的文章,总是沉思良久,怕自己写不好.今天我想要说的是wpf中datagrid控件.我们先来看看它在整个类的层次结构: ...
- wpf研究之道——datagrid控件分页
这是我们的datagrid分页效果图,有上一页,下一页,可以跳到任何一页.当页码比较多的时候,只显示几页,其余用点点,界面实现如下: <!--分页--> <StackPanel Or ...
- WPF的DataGrid控件从excel里复制数据然后粘贴
WPF的DataGrid控件不能像winform的DataGridView控件一样,支持值的粘贴.WPF的DataGrid控件本质上是跟数据绑定联系在一起,所以需要进行复制粘贴的操作,可以在wpf里用 ...
- WPF 4 DataGrid 控件(进阶篇一)
原文:WPF 4 DataGrid 控件(进阶篇一) 上一篇<WPF 4 DataGrid 控件(自定义样式篇)>中,我们掌握了DataGrid 列表头.行表头.行.单元格相关的 ...
- WPF 4 DataGrid 控件(进阶篇二)
原文:WPF 4 DataGrid 控件(进阶篇二) 上一篇<WPF 4 DataGrid 控件(进阶篇一)>中我们通过DataGridTemplateColumn 类自定义编辑 ...
随机推荐
- 每天一个linux命令(目录文件操作):【转载】Linux 目录结构
对于每一个Linux学习者来说,了解Linux文件系统的目录结构,是学好Linux的至关重要的一步.,深入了解linux文件目录结构的标准和每个目录的详细功能,对于我们用好linux系统至关重要,下面 ...
- BZOJ2005 NOI2010 能量采集 【莫比乌斯反演】
BZOJ2005 NOI2010 能量采集 Description 栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可以采集太阳光的能量.在这些植物采集能量后,栋栋再使用一个能量汇集机器把这些 ...
- jquery ajax 超时设置
自:jquery ajax超时设置 var ajaxTimeoutTest = $.ajax({ url:'', //请求的URL timeout : 1000, //超时时间设置,单位毫秒 typ ...
- python笔记-10(socket提升、paramiko、线程、进程、协程、同步IO、异步IO)
一.socket提升 1.熟悉socket.socket()中的省略部分 socket.socket(AF.INET,socket.SOCK_STREAM) 2.send与recv发送大文件时对于黏包 ...
- Flask第一篇——URL详解
原创 2018-02-14 孟船长 自动化测试实战 URL是Uniform Resource Locator的缩写,即统一资源定位符. 一个URL通常由一下几个部分组成: scheme://host: ...
- simulink使用system test测试 (matlab2014a)
simulink中有个工具system test,tools->systemtest->launch system test 打开.打开之后界面是这样的 选择insert->test ...
- 什么是spark(六)Spark中的对象
Spark中的对象 Spark的Conf,极简化的场景,可以设置一个空conf给sparkContext,在执行spark-submit的时候,系统会默认给sparkContext赋一个SparkCo ...
- CentOS 6.5 下MySql主从、主主配置
参考网站: http://blog.csdn.net/faye0412/article/details/6280761 http://blog.csdn.net/kk185800961/article ...
- Mac下docker搭建lnmp环境 + redis + elasticsearch
之前在windows下一直使用vagrant做开发, 团队里面也是各种开发环境,几个人也没有统一环境,各种上线都是人肉,偶尔还会有因为开发.测试.生产环境由于软件版本或者配置不一致产生的问题, 今年准 ...
- UCML 2.0 For ASP.NET开发平台简介
互联网时代,我们能跟上网络变革的步伐吗?我们的产品领先于竞争对手吗?我们能够满足日益个性化的客户需求吗? 采用新的软件开发方法是我们的首要选择. 第一个全面支持ASP.NET的应用框架开发平台诞生了— ...