简体   繁体   中英

Bind Datatable with DataGrid in WPF & MVVM

I am new to WPF, I am using MVVM pattern in WPF and generating a Datatable structure at the runtime, then binding Datatable with DataGrid/RadGridView, which is working as expected.

Problem: I want DataGrid/RadGridView configurable (where user can add new row, delete row and edit the data) and on save button click everything should be saved in the database. I have a situation where I need to create an empty DataTable with different columns (depending on user input). And then enter values under those columns and then on click on save need to save value in the database. I am able to bind DataTable to DataGrid (I can see all the column names and data rows if there is already some data in the DataTable in the grid) but NOT able to add (enter) or delete any row at the run time from DataGrid. I have set "True" value for CanUserDeleteRows and CanUserInsertRows. I am not sure where I am going wrong. I am implement INotifyPropertyChanged in my ViewModel class.

I am struggling to get the desired result.

My code looks like as below:

ViewModel--

    DataTable _manualDataTable;
    public DataTable ManualDataTable
    {
        get
        {
            return _manualDataTable;
        }
        set
        {
            _manualDataTable = value;
            OnPropertyChanged("ManualDataTable");
        }
    }

For creating DataTable--

    void LoadManualDataTable()
    {
        DataTable dtData = new DataTable();
        dtData.Columns.Add("TimeStamp", typeof(DateTime));
        List<DataColumn> columns = new List<DataColumn>();
        var query = _dataContext.GetSenData().Where(sen => sen.LogID == ((DataLogs)SelectedItemNode).Logger.LogID).Select(sen => sen.SeriesID);
        var queryTS = _dataContext.GetDataSeries().Where(ts => query.Contains(ts.SeriesID));
        foreach (DataSeries ts in queryTS)
        {
            var queryPLoc = _dataContext.GetDataLoc().Where(pLoc => pLoc.ParamID == ts.ParamID).Select(pLoc => pLoc.Name);
            dtData.Columns.Add(queryPLoc.First(), typeof(string));
        }

        ManualDataTable = dtData;
     }

XAML code--

     <DataGrid Grid.Row="0" AutoGenerateColumns="True" ItemsSource="{Binding ManualDataTable}" CanUserAddRows="True" CanUserDeleteRows="True" IsReadOnly="False"  Name="dataGridManualData"/>

DataTable is created as expected (from LoadManualDataTable method) and if I will add any row through the code then those rows will be binded and will be displayed in DataGrid. But I am not able to create or delete rows through DataGrid.

Any help will be highly appreciated.

Thanks in advance!

i create a simple testproject to get what you get, but its works without any problem. maybe you should post your code and state what does not work.

public partial class MainWindow : Window
{
    public DataTable MyTable { get; set; }

    public MainWindow()
    {
        InitializeComponent();

        this.MyTable= new DataTable();
        this.MyTable.Columns.Add("Test");
        var row1 = this.MyTable.NewRow();
        row1["Test"] = "dsjfks";

        this.MyTable.Rows.Add(row1);

        this.DataContext = this;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("rows: " + this.MyTable.Rows.Count);
    }

}

xaml

<DockPanel>
    <Button Height="23" Content="sdf" Click="Button_Click" />
    <DataGrid ItemsSource="{Binding MyTable}" CanUserAddRows="True"/>
</DockPanel>

I am not sure of my answer, but I am going to try...

I had the same problem of you: CanUserAddRows always false.

It turns out that the binding was ok, but the class which I was bindig did not have a default constructor.

this Works:

private ObservableCollection<Point> m_points;
public ObservableCollection<Point> Points
{
    get { return m_points; }
    set { m_points = value; }
}

public class Point
{
    public double X { get; set; }
    public double Y { get; set; }

    public Point()
    {
        this.X = 0;
        this.Y = 0;
    }

    public Point(double x, double y)
    {
        this.X = x;
        this.Y = y;
    }
}

this dont work:

private ObservableCollection<Point> m_points;
public ObservableCollection<Point> Points
{
    get { return m_points; }
    set { m_points = value; }
}

public class Point
{
    public double X { get; set; }
    public double Y { get; set; }

    public Point(double x, double y)
    {
        this.X = x;
        this.Y = y;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM