WPF DataGrid 控件的運用

WPF DataGrid 控件的運用html

運行環境:Window7 64bit,.NetFramework4.61,C# 6.0; 編者:烏龍哈里 2017-02-23前端


參考:express

章節:app

  • 添加列和數據源
  • 選擇單位設置
  • 自動添加行號
  • Enter 鍵作成 Tab 鍵的效果
  • 同步更新數據源
  • 在選中 Cell 所在行上插入新行或刪除選中 Cell 的所在行
  • 獲取選中單元格的值

正文: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>
View Code

 

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 }
View Code
相關文章
相關標籤/搜索