WPF MVVM将DataTable绑定到DataGrid不显示数据

时间:2015-12-10 05:19:29

标签: c# wpf mvvm datagrid datatable

我有一个简单的控件,其中包含一个DataSrid,ItemsSource绑定到DataTable。当我填充DataTable时,我可以看到在DataGrid中添加了行,但是没有显示数据。我没有为此DataGrid使用任何特殊样式(采用默认样式),唯一的设置是将AutoGenerateColumn设置为True。

在XAML中

<DataGrid AutoGenerateColumns="True" ItemsSource="{Binding TableResult}"/>

在视图模型中

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);
}

6 个答案:

答案 0 :(得分:2)

填充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代码:

<DataGrid ItemsSource="{Binding EmployeeDataTable}"/>

<强>更新

我已经测试了您的示例并且它可以正常工作,但您应该调用您的方法 填充FillTable()的构造函数中的DataTable。例如:

public class YourViewModel
{
    public YourViewModel()
    {  
        FillTable();
    }
}

答案 1 :(得分:0)

您还必须定义列:例如:

<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>

确保您已在视图模型中实施INotifyPropertyChanged

答案 2 :(得分:0)

你需要调用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;
        }

答案 3 :(得分:0)

您的ItemsSource需要是对象列表,而不是DataRow / Column。在任何情况下,在ViewModel上引用这些类型的东西都会破坏MVVM!

所以:

public List<Result> TableResult {get;set;} // raise property change on set

public class Result 
{
public string Color {get;set;}
public int Number {get;set;}
}

编辑:由于您事先对表本身一无所知,我建议您使用一个简单的字符串列表来生成行和列。

这样的事情:

    public List<List<string>> TableResult { get; set; } // raise property changed

        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;

然后,您必须创建转换器以将行转换为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();
    }
}
在您的XAML上

,将其添加到您的资源(例如UserControl.Resources):

        <local:ListToTables x:Key="listToTables"></local:ListToTables>

其中&#34;本地&#34;是转换器的添加命名空间,并且:

    <DataGrid ItemsSource="{Binding TableResult,Converter={StaticResource listToTables}}" >

用于您的DataGrid。

enter image description here

编辑决赛:

如果您认为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;

您必须将DataTable设置为引发属性更改。添加它不会做任何事情;)

答案 4 :(得分:0)

如果我添加以下内容,您的代码将适用于我

<a>

答案 5 :(得分:0)

我刚刚对此进行了角力,发现了另一个非常可靠的答案,该答案包含了此处的部分但并非全部其他内容。 Xaml(假设datacontext是在页面级别设置的):

<DataGrid ItemsSource="{Binding Findings}" />

ViewModel中的代码(假设使用数据创建了DataTable)

Findings = null;
Findings = dataTable.DefaultView

关键是首先将绑定属性显式设置为null。我发现在WinForms中也是如此。