WPF DataGrid 控件的運用html
運行環境:Window7 64bit,.NetFramework4.61,C# 6.0; 編者:烏龍哈里 2017-02-23前端
參考:express
章節:app
正文:ide
1、添加列和數據源:學習
咱們往一個 DataGrid 中添加數據源 List< int[] >,注意要在 XAML 代碼中把自動添加列的屬性給設成 False, AutoGenerateColumns="False" 。ui
示例1:
C# 代碼片斷: spa
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;
3d
前端 XAML 片斷: code
<DataGrid Name="dtgShow" AutoGenerateColumns="False" Margin="3" Grid.Row="0" Grid.ColumnSpan="2"/>
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"/>
運行結果如圖:
3、自動添加行號:
直接在 DataGrid 的 LoadingRow() 事件中寫:
示例3:
C# 代碼片斷:
private void dtgShow_LoadingRow(object sender, DataGridRowEventArgs e)
{
e.Row.Header = e.Row.GetIndex() + 1;
}
4、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;
}
}
運行效果圖,後面藍色方塊動是我左右鍵輸入才動的:
5、同步更新數據源:
若是 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>
6、在選中 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);
}
}
7、獲取選中單元格的值
方法一:在上面的示例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 代碼:
1 <Window x:Class="學習WpfDataGrid1.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 mc:Ignorable="d" 7 Title="MainWindow" Height="300" Width="250"> 8 <Grid > 9 <Grid.RowDefinitions> 10 <RowDefinition Height="24"/> 11 <RowDefinition Height="5*"/> 12 <RowDefinition Height="1*"/> 13 <RowDefinition Height="1*"/> 14 <RowDefinition Height="1*"/> 15 </Grid.RowDefinitions> 16 <Grid.ColumnDefinitions> 17 <ColumnDefinition Width="1*"/> 18 <ColumnDefinition Width="1*"/> 19 </Grid.ColumnDefinitions> 20 <CheckBox Name="chkResult" Content="查看數據" Margin="3" Grid.Row="0" Grid.Column="1" Click="chkResult_Click" /> 21 <ListBox Name="lbxData" Visibility="Hidden" Grid.Row="1" Grid.ColumnSpan="2"/> 22 <ComboBox Name="cbbSelectMode" Margin="2" SelectionChanged="cbbSelectMode_SelectionChanged"/> 23 <DataGrid Name="dtgShow" AutoGenerateColumns="False" Margin="3" Grid.Row="1" Grid.ColumnSpan="2" LoadingRow="dtgShow_LoadingRow" PreviewKeyDown="dtgShow_PreviewKeyDown" SelectedCellsChanged="dtgShow_SelectedCellsChanged" /> 24 <TextBox Name="tbxSelect" Grid.Row="2" Grid.ColumnSpan="2"/> 25 <Button Name="btnAppend" Content="Append" Margin="3" Grid.Row="3" Grid.Column="0" Click="btnAppend_Click" /> 26 <Button Name="btnRemoveLast" Content="Remove Last" Margin="3" Grid.Row="3" Grid.Column="1" Click="btnRemoveLast_Click"/> 27 <Button Name="btnInsert" Content="Insert" Margin="3" Grid.Row="4" Grid.Column="0" Click="btnInsert_Click" /> 28 <Button Name="btnRemoveSelect" Content="Remove Selected" Margin="3" Grid.Row="4" Grid.Column="1" Click="btnRemoveSelect_Click" /> 29 </Grid> 30 </Window>
C# 代碼:
1 using System.Collections.Generic; 2 using System.Collections.ObjectModel; 3 using System.Data; 4 using System.Linq; 5 using System.Text; 6 using System.Windows; 7 using System.Windows.Controls; 8 using System.Windows.Data; 9 using System.Windows.Input; 10 11 namespace 學習WpfDataGrid1 12 { 13 /// <summary> 14 /// MainWindow.xaml 的交互邏輯 15 /// </summary> 16 public partial class MainWindow : Window 17 { 18 List<int[]> list = new List<int[]>(); 19 ObservableCollection<int[]> showdata = new ObservableCollection<int[]>(); 20 21 public MainWindow() 22 { 23 InitializeComponent(); 24 AddSource(); 25 GetComboBoxSource(); 26 GetShowData(); 27 } 28 //---原始數據源到顯示數據源 29 private void GetShowData() 30 { 31 showdata.Clear(); 32 foreach (var a in list) 33 { 34 showdata.Add(a); 35 } 36 dtgShow.ItemsSource = showdata; 37 } 38 //---顯示數據到原始數據 39 private void GetRawData() 40 { 41 list.Clear(); 42 foreach (var a in showdata) 43 { 44 list.Add(a); 45 } 46 } 47 //---添加 ComboBox 數據源 48 private void GetComboBoxSource() 49 { 50 //cbbSelectMode 爲 ComboBox 控件實例 51 cbbSelectMode.Items.Add(DataGridSelectionUnit.Cell); 52 cbbSelectMode.Items.Add(DataGridSelectionUnit.FullRow); 53 cbbSelectMode.Items.Add(DataGridSelectionUnit.CellOrRowHeader); 54 cbbSelectMode.SelectedIndex = 2; 55 56 } 57 //---DataGrid 選擇方式 58 private void cbbSelectMode_SelectionChanged(object sender, SelectionChangedEventArgs e) 59 { 60 dtgShow.SelectionUnit = (DataGridSelectionUnit)cbbSelectMode.SelectedValue; 61 } 62 //---添加 DataGrid 數據源 63 private void AddSource() 64 { 65 list.Add(new int[] { 1, 2, 3, 4, 5 }); 66 list.Add(new int[] { 2, 3, 4, 5, 6 }); 67 list.Add(new int[] { 3, 4, 5, 6, 7 }); 68 69 int _col = list[0].Length; 70 //int _row = list.Count; 71 for (int i = 0; i < _col; i++) 72 { 73 dtgShow.Columns.Add(new DataGridTextColumn 74 { 75 Width = (Width - 38) / _col, 76 Header = $"{(char)(65 + i)}", 77 Binding = new Binding($"[{i.ToString()}]") 78 }); 79 } 80 } 81 //---自動添加行號 82 private void dtgShow_LoadingRow(object sender, DataGridRowEventArgs e) 83 { 84 e.Row.Header = e.Row.GetIndex() + 1; 85 } 86 //---Enter 達到 Tab 的效果 87 private void dtgShow_PreviewKeyDown(object sender, KeyEventArgs e) 88 { 89 var uie = e.OriginalSource as UIElement; 90 if (e.Key == Key.Enter) 91 { 92 uie.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); 93 e.Handled = true; 94 } 95 } 96 //---給lbxData(ListBox) 添加數據 97 private void GetListBoxSource() 98 { 99 lbxData.Items.Clear(); 100 StringBuilder sb = new StringBuilder(); 101 foreach (var a in list) 102 { 103 sb.Clear(); 104 foreach (var b in a) 105 { 106 sb.Append(b.ToString()); 107 sb.Append(" "); 108 } 109 lbxData.Items.Add(sb.ToString()); 110 } 111 } 112 //---切換 DataGrid 和 ListBox 113 private void chkResult_Click(object sender, RoutedEventArgs e) 114 { 115 CheckBox chk = (CheckBox)sender; 116 if (chk.IsChecked == true) 117 { 118 dtgShow.Visibility = Visibility.Hidden; 119 lbxData.Visibility = Visibility.Visible; 120 GetRawData(); 121 GetListBoxSource(); 122 } 123 else 124 { 125 lbxData.Visibility = Visibility.Hidden; 126 dtgShow.Visibility = Visibility.Visible; 127 GetShowData(); 128 } 129 } 130 //增長新行 131 private void btnAppend_Click(object sender, RoutedEventArgs e) 132 { 133 showdata.Add(new int[dtgShow.Columns.Count]); 134 } 135 //刪除末行 136 private void btnRemoveLast_Click(object sender, RoutedEventArgs e) 137 { 138 if (showdata.Count > 0) 139 { 140 showdata.RemoveAt(showdata.Count - 1); 141 } 142 } 143 //---取得選中 Cell 所在的行列 144 private bool GetCellXY(DataGrid dg, ref int rowIndex, ref int columnIndex) 145 { 146 var _cells = dg.SelectedCells; 147 if (_cells.Any()) 148 { 149 rowIndex = dg.Items.IndexOf(_cells.First().Item); 150 columnIndex = _cells.First().Column.DisplayIndex; 151 return true; 152 } 153 return false; 154 } 155 //在選中 Cell 所在行上插入新行 156 private void btnInsert_Click(object sender, RoutedEventArgs e) 157 { 158 int _rowIndex = 0; 159 int _columnIndex = 0; 160 if (GetCellXY(dtgShow, ref _rowIndex, ref _columnIndex)) 161 { 162 showdata.Insert(_rowIndex, new int[dtgShow.Columns.Count]); 163 } 164 } 165 //刪除選中 Cell 所在行 166 private void btnRemoveSelect_Click(object sender, RoutedEventArgs e) 167 { 168 int _rowIndex = 0; 169 int _columnIndex = 0; 170 if (GetCellXY(dtgShow, ref _rowIndex, ref _columnIndex)) 171 { 172 showdata.RemoveAt(_rowIndex); 173 } 174 } 175 //---獲取全部的選中cell 的值 176 private string GetSelectedCellsValue(DataGrid dg) 177 { 178 var cells = dg.SelectedCells; 179 StringBuilder sb = new StringBuilder(); 180 if (cells.Any()) 181 { 182 foreach(var cell in cells) 183 { 184 sb.Append((cell.Column.GetCellContent(cell.Item) as TextBlock).Text); 185 sb.Append(" "); 186 } 187 } 188 return sb.ToString(); 189 } 190 //---顯示選中單元格的值 191 private void dtgShow_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e) 192 { 193 tbxSelect.Text = GetSelectedCellsValue(dtgShow); 194 } 195 } 196 }