3
votes

I want to display a SQL table in my WPF Datagrid, writing SQL query at runtime. I've built my View (simplified) and ViewModel associated:

View:

-----------------MyDataGrid.xaml-----------------

<DataGrid x:Name="CurrentSqlGrid" 
          ItemsSource="{Binding Path=CurrentDataTable,Mode=OneWay}"  
          Grid.Row="2" AutoGenerateColumns="True"  IsReadOnly="True" />
<TextBox x:Name="TextBoxSql" Height="120" Grid.Row="1" 
         TextWrapping="Wrap" VerticalAlignment="Top"/>

-----------------MyDataGrid.cs-----------------

public partial class MyDataGrid : UserControl
{
    private SqlDataGridViewModel sqlDataGridViewModel;

    public MyDataGrid()
    {
        InitializeComponent();
        sqlDataGridViewModel = new SqlDataGridViewModel();
        this.DataContext = sqlDataGridViewModel;
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        sqlDataGridViewModel.FillDataTableWithQuery(TextBoxSql.Text);          
    }
}

ViewModel:

-----------------SqlDataGridViewModel.cs-----------------

public class SqlDataGridViewModel 
{
    private DataTable _dataTable;
    private SqlDataAdapter _adapter;

    public DataTable CurrentDataTable
    {
        get
        {
            return _dataTable;
        }
        set
        {
            _dataTable = value;
        }
    }

    public SqlDataGridViewModel()
    {
        _dataTable = new DataTable("QUERY");
        FillDataTableWithQuery("SELECT TOP 500 * FROM XUSER");           
    }

    public void FillDataTableWithQuery(string query)
    {
        CurrentDataTable.Reset();
        CurrentDataTable.Clear();

        try
        {
            using (SqlConnection sqlConn = new SqlConnection(SessionProvider.Instance.currentConnectionString))
            {
                _adapter = new SqlDataAdapter(query, sqlConn);
                _adapter.Fill(CurrentDataTable);
            }
        }
        catch (Exception ex)
        {
            MartuLogger.Instance.Error("Exception in SqlDataGridViewModel :" + ex.Message);
        }
    }
}

This solution display me first DataTable of first query.

But when I write another SQL query, I call FillDataTableWithQuery("SELECT * from another_table") and Datagrid clears all rows but it doesn't load new columns and new rows! (only display old columns!). In debug, the CurrentDataTable contains new query's results.... Any ideas?

SOLUTION With Help of Faisal Hafeez we 've found this solution:

Xaml and code behind are the same. it work with OneWay and TwoWay mode.

My view model becomes :

public class SqlDataGridViewModel : INotifyPropertyChanged
{
    private DataTable _dataTable;
    private SqlDataAdapter _adapter;
    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChange(string PropertyName)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
    }

    public DataTable CurrentDataTable
    {
        get
        {
            return _dataTable;
        }
        set
        {
            _dataTable = value;
            //NotifyPropertyChange("CurrentDataTable");
        }
    }

    public SqlDataGridViewModel()
    {
        _dataTable = new DataTable("QUERY");
        FillDataTableWithQuery("SELECT TOP 500 * FROM XUSER");           
    }

    public void FillDataTableWithQuery(string query)
    {
        _dataTable = new DataTable("QUERY");

        try
        {
            using (SqlConnection sqlConn = new SqlConnection(SessionProvider.Instance.currentConnectionString))
            {
                _adapter = new SqlDataAdapter(query, sqlConn);
                _adapter.Fill(CurrentDataTable);
            }

            NotifyPropertyChange("CurrentDataTable");
        }
        catch (Exception ex)
        {
            MartuLogger.Instance.Error("Exception in SqlDataGridViewModel :" + ex.Message);
        }
    }
}

If i don't NotifyPropertyChange after _adapter.Fill, view doesn't refresh. (I've tried to notify in Set CurrentTable, but _adapter.Fill evidently don't call CurrentTable's set method). Thank you.

1
You need to tell your view that table has been updated. Your viewmodel needs to implement NotifyOfPropertyChanged.fhnaseer
I've tried with INotifyPropertyChanged, but nothingdavymartu

1 Answers

1
votes

Try this. You need to implement INotifyPropertyChanged and call PropertyChanged on set event of datagrid.

public class SqlDataGridViewModel : INotifyPropertyChanged {

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(String info)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
}

public DataTable CurrentDataTable
    {
        get
        {
            return _dataTable;
        }
        set
        {
            _dataTable = value;
            OnPropertyChanged("CurrentDataTable");
        }
    }
}