DataGrid删除或者列以后,需要先清空DataGrid的ItemsSouce,再重新给DataGrid绑定数据源,

直接在ViewModel里面对数据源进行添加和删除,不会反应到界面上,

在MVVM模式下面,如果直接把控件通过CommandParameter传到ViewModel进行修改,就显得很别扭

想了很久,才想到这个方法,如果大佬们有更好的方法,也可以指导下。

首先准备一个命令类 

 1 public class RelayCommand : ICommand
 2     {
 3         private Action<Action<string>> _addColumn;
 4 
 5         public RelayCommand(Action<Action<string>> addColumn)
 6         {
 7             _addColumn = addColumn;
 8         }
 9 
10         public event EventHandler CanExecuteChanged;
11 
12         public bool CanExecute(object parameter)
13         {
14             return true;
15         }
16 
17         public void Execute(object parameter)
18         {
19             _addColumn?.Invoke(parameter as Action<string>);
20         }
21     }

然后准备一个转换器 关键就是这个 他会把添加列的执行方法传递给ViewModel

 1 public class ColumnConverter : IValueConverter
 2     {
 3         private DataGrid _dataGrid;
 4 
 5         public void AddColumn(string name)
 6         {
 7             //如果存在相同名称 就直接return
 8             for (int i = 0; i < _dataGrid.Columns.Count; i++)
 9             {
10                 var col = _dataGrid.Columns[i];
11                 if (col.Header.ToString() == name)
12                 {
13                     return;
14                 }
15             }
16 
17             //添加列和绑定数据
18             _dataGrid.Columns.Add(new DataGridTextColumn() { Header = name, Binding = new Binding(name) });
19         }
20 
21         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
22         {
23             _dataGrid = value as DataGrid;
24 
25             //把添加列的执行方法返回给ViewModel
26             return new Action<string>(AddColumn);
27         }
28 
29         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
30         {
31             throw new NotImplementedException();
32         }
33     }

再准备一个ViewModel类,验证逻辑就先省略了

 1 public class MainViewModel : INotifyPropertyChanged
 2     {
 3         private string _columnName;
 4 
 5         private DataTable _data;
 6 
 7         public RelayCommand AddColumnCmd { get; set; }
 8 
 9         public DataTable Data
10         {
11             get => _data;
12             set => _data = value;
13         }
14 
15         public RelayCommand DelColumnCmd { get; set; }
16 
17         public MainViewModel()
18         {
19             //初始化数据
20             InitialData();
21 
22             //初始化命令
23             AddColumnCmd = new RelayCommand(AddColumn);
24             DelColumnCmd = new RelayCommand(DelColumn);
25         }
26 
27         public string Name
28         {
29             get { return _columnName; }
30             set { _columnName = value; OnPropertyChanged(); }
31         }
32 
33         public event PropertyChangedEventHandler PropertyChanged;
34 
35         private void AddColumn(Action<string> action)
36         {
37             action?.Invoke(Name);
38             Data.Columns.Add(new DataColumn() { ColumnName = Name });
39         }
40 
41         private void DelColumn(Action<string> action)
42         {
43             action?.Invoke(Name);
44 
45             Data.Columns.Remove(Name);
46         }
47 
48         /// <summary>
49         /// 初始化数据
50         /// </summary>
51         private void InitialData()
52         {
53             Data = new DataTable();
54             for (int i = 0; i < 5; i++)
55             {
56                 var col = new DataColumn() { ColumnName = (i + 1).ToString().PadLeft(2, '0') };
57                 Data.Columns.Add(col);
58             }
59 
60             for (int i = 0; i < 10; i++)
61             {
62                 var row = Data.NewRow();
63                 for (int j = 0; j < Data.Columns.Count; j++)
64                 {
65                     row[j] = i * j;
66                 }
67                 Data.Rows.Add(row);
68             }
69         }
70 
71         private void OnPropertyChanged([CallerMemberName] string name = null)
72         {
73             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
74         }
75     }

然后是界面 ,绑定各种数据

 1 <Window
 2     x:Class="DataGrid动态添加列.MainWindow"
 3     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 4     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 5     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 6     xmlns:local="clr-namespace:DataGrid动态添加列"
 7     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 8     Title="MainWindow"
 9     Width="800"
10     Height="450"
11     mc:Ignorable="d">
12     <Window.DataContext>
13         <local:MainViewModel />
14     </Window.DataContext>
15     <Window.Resources>
16         <local:ColumnConverter x:Key="Converter" />
17     </Window.Resources>
18     <Grid>
19         <StackPanel Orientation="Vertical">
20             <TextBox Height="30" Text="{Binding Name}" />
21             <Button
22                 Command="{Binding AddColumnCmd}"
23                 CommandParameter="{Binding ElementName=grid, Converter={StaticResource Converter}}"
24                 Content="添加列" />
25             <DataGrid x:Name="grid" ItemsSource="{Binding Data}" />
26         </StackPanel>
27     </Grid>
28 </Window>

最终效果

WPF MVVM模式下DataGrid动态增加列与删除列_数据