WPF MVVM 将 DataTable 绑定到 DataGrid 不显示数据
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34194236/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF MVVM Bind DataTable to DataGrid does not display data
提问by GuillaumeA
I've got a simple control which contains a DataGrid which ItemsSource is bound to a DataTable. When I fill the DataTable, I can see that rows are added in the DataGrid, but no data is displayed. I don't use any special style for this DataGrid (take the default one), the only setting is the AutoGenerateColumn set to True.
我有一个简单的控件,其中包含一个 DataGrid,ItemsSource 绑定到一个 DataTable。当我填充DataTable时,可以看到DataGrid中添加了行,但没有显示任何数据。我没有为此 DataGrid 使用任何特殊样式(采用默认样式),唯一的设置是 AutoGenerateColumn 设置为 True。
In the XAML
在 XAML 中
<DataGrid AutoGenerateColumns="True" ItemsSource="{Binding TableResult}"/>
In the view model
在视图模型中
private DataTable tableResult = new DataTable();
public DataTable TableResult
{
get { return tableResult; }
set { tableResult = value; OnPropertyChanged("TableResult"); }
}
private void FillTable()
{
DataColumn c = new DataColumn();
c.ColumnName = "Col1";
this.TableResult.Columns.Add(c);
c = new DataColumn();
c.ColumnName = "Col2";
this.TableResult.Columns.Add(c);
DataRow row1 = this.TableResult.NewRow();
row1["Col1"] = "Blue";
row1["Col2"] = "12";;
this.TableResult.Rows.Add(row1);
DataRow row2 = this.TableResult.NewRow();
row2["Col1"] = "Red";
row2["Col2"] = "18";
this.TableResult.Rows.Add(row2);
DataRow row3 = this.TableResult.NewRow();
row3["Col1"] = "Yellow";
row3["Col2"] = "27";
this.TableResult.Rows.Add(row3);
}
回答by StepUp
Working example of populating data of DataGrid:
填充 DataGrid 数据的工作示例:
public MyViewModel()//constructor of MyViewModel
{
FillMyDataGrid();
}
private DataTable employeeDataTable;
public DataTable EmployeeDataTable
{
get { return employeeDataTable; }
set
{
employeeDataTable = value;
OnPropertyChanged("EmployeeDataTable");
}
}
public FillMyDataGrid()
{
var _ds = new DataSet("Test");
employeeDataTable = new DataTable();
employeeDataTable = _ds.Tables.Add("DT");
for (int i = 0; i < 50; i++)
{
//employeeDataTable.Columns.Add(i.ToString() + ".");
employeeDataTable.Columns.Add(i.ToString());
}
for (int i = 0; i < 2; i++)
{
var theRow = employeeDataTable.NewRow();
for (int j = 0; j < 50; j++)
{
theRow[j] = "a";
}
employeeDataTable.Rows.Add(theRow);
}
}
XAML code:
XAML 代码:
<DataGrid ItemsSource="{Binding EmployeeDataTable}"/>
Update:
更新:
I've tested your example and it works correctly, but you should call your method
FillTable()in constructor to populate DataTable. For example:
我已经测试了您的示例并且它可以正常工作,但是您应该FillTable()在构造函数中调用您的方法
来填充DataTable. 例如:
public class YourViewModel
{
public YourViewModel()
{
FillTable();
}
}
回答by DavidFromPhila
I just wrestled with this and found another answer I have found very reliable that incorporates some but not all of what others here have contributed. The Xaml (assumes datacontext is set at the page level):
我刚刚解决了这个问题,并找到了另一个我认为非常可靠的答案,其中包含了其他人贡献的一些但并非全部内容。Xaml(假设数据上下文设置在页面级别):
<DataGrid ItemsSource="{Binding Findings}" />
The code in the ViewModel (assumes a DataTable is created with data):
ViewModel 中的代码(假设 DataTable 是用数据创建的):
Findings = null;
Findings = dataTable.DefaultView
The key thing is to explicitly set the bound property to null first. I have found this to be true in WinForms as well.
关键是首先将绑定属性显式设置为 null。我发现这在 WinForms 中也是如此。
回答by sujith karivelil
You have to define your columns too: for example:
您也必须定义您的列:例如:
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Source=TableResult}" >
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding col1}"/>
<DataGridTextColumn Header="Surname" Binding="{Binding col2}"/>
<DataGridTextColumn Header="Phone" Binding="{Binding col3}" />
</DataGrid.Columns>
</DataGrid>
And ensure that you have implemented INotifyPropertyChangedin the view model
并确保您已INotifyPropertyChanged在视图模型中实现
回答by Sajeetharan
You need to call DefaultView, here is the change in FillTable() Method,
需要调用DefaultView,这里是FillTable()方法的变化,
private void FillTable()
{
DataColumn c = new DataColumn();
c.ColumnName = "Col1";
this.TableResult.Columns.Add(c);
c = new DataColumn();
c.ColumnName = "Col2";
this.TableResult.Columns.Add(c);
DataRow row1 = this.TableResult.NewRow();
row1["Col1"] = "Blue";
row1["Col2"] = "12"; ;
this.TableResult.Rows.Add(row1);
DataRow row2 = this.TableResult.NewRow();
row2["Col1"] = "Red";
row2["Col2"] = "18";
this.TableResult.Rows.Add(row2);
DataRow row3 = this.TableResult.NewRow();
row3["Col1"] = "Yellow";
row3["Col2"] = "27";
this.TableResult.Rows.Add(row3);
dataGrid1.ItemsSource = this.tableResult.DefaultView;
}
回答by Tyress
Your ItemsSource would need to be a List of objects, not a DataRow/Column. In any case referencing these sorts of things on the ViewModel breaks MVVM!
您的 ItemsSource 需要是一个对象列表,而不是 DataRow/Column。在任何情况下,在 ViewModel 上引用这些东西都会破坏 MVVM!
So:
所以:
public List<Result> TableResult {get;set;} // raise property change on set
and
和
public class Result
{
public string Color {get;set;}
public int Number {get;set;}
}
EDIT: Since you don't know anything about the table itself beforehand, I suggest you use a simple List of List of Strings to produce your rows and columns.
编辑:由于您事先对表格本身一无所知,我建议您使用简单的字符串列表列表来生成行和列。
Something like this:
像这样的东西:
public List<List<string>> TableResult { get; set; } // raise property changed
and
和
List<string> columns = new List<string>() { "Col1", "Col2", "Col3", "Col4" };
List<string> row1 = new List<string>() { "a", "b", "c", "d" };
List<string> row2 = new List<string>() { "w", "x", "y", "z" };
List<List<string>> table = new List<List<string>>(){columns,row1,row2};
TableResult = table;
You then must create a converter to convert your rows into a DataTable:
然后,您必须创建一个转换器来将您的行转换为 DataTable:
public class ListToTables : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var list = value as List<List<string>>;
var headers = list.First();
DataTable dt = new DataTable();
foreach (string header in headers)
{
dt.Columns.Add(header);
}
foreach (List<string> row in list.Skip(1))
{
int index = 0;
DataRow r = dt.NewRow();
foreach (string col in row)
{
r[index++] = col;
}
dt.Rows.Add(r);
}
return dt;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
on your XAML, add this to your resources (e.g. UserControl.Resources):
在您的 XAML 上,将其添加到您的资源中(例如 UserControl.Resources):
<local:ListToTables x:Key="listToTables"></local:ListToTables>
where "local" is the added namespace of your converter, and:
其中“local”是转换器添加的命名空间,并且:
<DataGrid ItemsSource="{Binding TableResult,Converter={StaticResource listToTables}}" >
for your DataGrid.
为您的 DataGrid。
EDIT FINAL:
编辑最终:
You can keep your DataTable if you believe MVVM allows it, just replace the latter part of your code with this:
如果您认为 MVVM 允许,您可以保留您的 DataTable,只需将代码的后半部分替换为:
DataTable tempDataTable = new DataTable();
DataColumn c = new DataColumn();
c.ColumnName = "Col1";
tempDataTable.Columns.Add(c);
c = new DataColumn();
c.ColumnName = "Col2";
tempDataTable.Columns.Add(c);
DataRow row1 = tempDataTable.NewRow();
row1["Col1"] = "Blue";
row1["Col2"] = "12";;
tempDataTable.Rows.Add(row1);
DataRow row2 = tempDataTable.NewRow();
row2["Col1"] = "Red";
row2["Col2"] = "18";
tempDataTable.Rows.Add(row2);
DataRow row3 = tempDataTable.NewRow();
row3["Col1"] = "Yellow";
row3["Col2"] = "27";
tempDataTable.Rows.Add(row3);
this.DataTable = tempDataTable;
You have to set the DataTable to raise property changed. Adding to it won't do anything ;)
您必须设置 DataTable 以提高属性更改。添加到它不会做任何事情;)
回答by blindmeis
your code works for me if i add the following
如果我添加以下内容,您的代码对我有用
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
FillTable();
DataContext = this;
}


