3
votes

I am new to MVVM and databinding and I am having some trouble binding a gridview to a datatable dynamically. I am able to get the column headers to bind, but no data is being displayed in the grid itself.

My model simply returns a data table as the result of a SQL string passed to it. My viewmodel just wraps the datatable and gets bound to the view.

Right now I am just trying to display the data by populating the gridview from the main window, but only the headers are being displayed.

I know there is data in the model.Results datatable though.

My viewmodel:

public class ResultsViewModel
{
    private DataTable _dt;

    public ResultsViewModel()
    {
        DataSource _ds = new DataSource();

        _dt = _ds.Execute("select * from tbl_users");
    }

    public DataTable Results
    {
        get { return _dt; }
        set { _dt = value; }
    }
}

My code to populate the gridview from the mainwindow:

public MainWindow()
    {
        InitializeComponent();

        ResultsView view = new ResultsView();
        ResultsViewModel model = new ResultsViewModel();

        GridView Grid = new GridView();

        foreach (DataColumn col in model.Results.Columns)
        {
            Grid.Columns.Add(new GridViewColumn
            {
                Header = col.ColumnName,
                DisplayMemberBinding = new Binding(col.ColumnName)
            });
        }

        view._listView.View = Grid;
        view.DataContext = model;

        view.SetBinding(ListView.ItemsSourceProperty, new Binding());

        _placeholder.Content = view;
    }

The ResultsView xaml:

<UserControl x:Class="InDevReporting.Views.ResultsView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <ListView x:Name="_listView" />
</Grid>

1

1 Answers

2
votes

Try setting your data context to model.Results.

ie change this line:

view.DataContext = model;

to this:

view.DataContext = model.Results;

Generally you would create a dependency property on your view model and specify the binding in the XAML. The grid should be clever enough to figure out what columns to draw:

<ListView ItemsSource="{Binding Results}" />

public MainWindow()
{
    InitializeComponent();

    // your code to instance and populate model

    this.DataContext = model;
}

public class ResultsViewModel : DependencyObject
{
    public static readonly DependencyProperty ResultsProperty = DependencyProperty.Register("Results", typeof(DataTable) , typeof(ResultsViewModel));
    public DataTable Results
    {
        get { (DataTable)GetValue(ResultsProperty); }
        set { SetValue(ResultsProperty, value); }
    }
}

I've tapped this out from memory, so apologies if the code isn't exactly right. The easiest way to declare a new dependency property is to use the propdp code snippet. It's a lot of syntax to memorize.