Search code examples
c#wpfmvvmdatagrid

How can I show data in DataGrid when I press button in WPF Mvvm?


I want to make the data appear on the data grid when I press the button using MVVM. When you invoke a method directly from the constructor, the data appears, but when you press the button, the data does not appear.

this is my code

MyViewModel.cs

public class MyViewModel : INotifyPropertyChanged
{

    static string strConn = "";
    MySqlConnection con;
    MySqlCommand cmd;
    MySqlDataAdapter adapter;
    DataSet ds;
    Boolean dataOnOff = false;
    public ObservableCollection<Students> _students = new ObservableCollection<Students>();
    public ObservableCollection<Students> Students
    {
        get { return _students; }
        set
        {
            if (_students == value) return;
            _students = value;
        }
    }

    public MyViewModel()
    {



        ReadCommand = new RelayCommand(DoRead);
    }


    public void FillList(object param)
    {
        if (dataOnOff == true)
        {
            try
            {

                con = new MySqlConnection(strConn);
                con.Open();
                cmd = new MySqlCommand("select * from student", con);
                adapter = new MySqlDataAdapter(cmd);
                ds = new DataSet();
                adapter.Fill(ds, "student");

                if (_students == null)
                    _students = new ObservableCollection<Students>();

                foreach (DataRow dr in ds.Tables[0].Rows)
                {
                    _students.Add(new Students
                    {
                        grade = Convert.ToInt32(dr[0].ToString()),
                        cclass = Convert.ToInt32(dr[1].ToString()),
                        name = Convert.ToString(dr[2].ToString()),
                        no = Convert.ToInt32(dr[3].ToString()),
                        score = Convert.ToString(dr[4].ToString())
                    });
                }

            }
            catch (Exception ex)
            {

            }

            finally
            {
                ds = null;
                adapter.Dispose();
                con.Close();
                con.Dispose();
            }
            dataOnOff = false;
        }
    }



    public event PropertyChangedEventHandler PropertyChanged;

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


    public RelayCommand ReadCommand { get; set; }
    public RelayCommand SaveCommand { get; set; }
    public RelayCommand AddUserCommand { get; set; }
    public RelayCommand DeleteUserCommand { get; set; }


    public void DoRead(object param)
    {
        FillList(param);
        dataOnOff = true;
        MessageBox.Show("s");
    }

}

MainWindow.xaml

<DockPanel LastChildFill="False">
        <Border DockPanel.Dock="Left" Width="610"  Padding="10">
            <DataGrid Width="590" Height="400" HorizontalAlignment="Left" Name="studentDataGrid" ColumnWidth="*" AutoGenerateColumns="False"
                      Grid.Row="1" ItemsSource="{Binding students, NotifyOnTargetUpdated=True,UpdateSourceTrigger=PropertyChanged}">

                <DataGrid.Columns>
                    <DataGridTextColumn Header="grade" Binding="{Binding grade,NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged}"/>
                    <DataGridTextColumn Header="class" Binding="{Binding cclass, NotifyOnTargetUpdated=True,UpdateSourceTrigger=PropertyChanged}" Foreground="Black"/>
                    <DataGridTextColumn Header="name" Binding="{Binding name, NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged}"/>
                    <DataGridTextColumn Header="no" Binding="{Binding no, NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged}"/>
                    <DataGridTextColumn Header="score" Binding="{Binding score, NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged}"/>

                </DataGrid.Columns>
            </DataGrid>
        </Border>
        <Border DockPanel.Dock="Right" Width="180"  Padding="0">
            <Grid >
                <Grid.RowDefinitions>
                    <RowDefinition Height="25*"/>
                    <RowDefinition Height="25*"/>
                    <RowDefinition Height="25*"/>
                    <RowDefinition Height="25*"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="15*"/>
                    <ColumnDefinition Width="35*"/>
                    <ColumnDefinition Width="15*"/>
                </Grid.ColumnDefinitions>
            <Button x:Name="ReadBtn" Content="READ" VerticalAlignment="Center" Height="25" Margin="10,15,10,15"  Grid.Row="0" Grid.Column="1" Command="{Binding ReadCommand}"/>
                <Button x:Name="InsertBtn" Content="INSERT" VerticalAlignment="Center" Height="25" Margin="10"  Grid.Row="1" Grid.Column="1" />
                <Button x:Name="UpdateBtn" Content="UPDATE" VerticalAlignment="Center" Height="25" Margin="10"  Grid.Row="2" Grid.Column="1" />
                <Button x:Name="DeleteBtn" Content="DELETE" VerticalAlignment="Center" Height="25" Margin="10"  Grid.Row="3" Grid.Column="1"/>
            </Grid>
        </Border>


    </DockPanel>

RelayCommand.cs

 public class RelayCommand : ICommand
{
    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;

    public RelayCommand(Action<object> execute) : this(execute, null)
    {

    }

    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }
}

I want to make the data visible in the data grid when the button is pressed. How can I fix it?? 😭


Solution

  • You need to do the following.

    1. Call OnPropertyChanged in Students property:
    public ObservableCollection<Students> Students
    {
        get { return _students; }
        set
        {
            if (_students == value) return;
            _students = value;
            OnPropertyChanged(nameof(Students));
        }
    }
    
    1. Set dataOnOff variable to true in ViewModel constructor:
    public MyViewModel()
    {
        dataOnOff = true;
        ReadCommand = new RelayCommand(DoRead);
    }
    
    1. Call FillList method in DoRead, as mentioned in comments:
    public void DoRead(object param)
    {
        FillList(param);
        dataOnOff = true;
        MessageBox.Show("s");
    }
    
    1. Specify a ViewModel for your window:
    <Window.DataContext>
        <nameSpace:MyViewModel/>
    </Window.DataContext>
    

    UPDATED

    1. Change ItemsSource binding statement like this (I changed (s)tudents to (S)tudents):
    ItemsSource="{Binding Students, NotifyOnTargetUpdated=True,UpdateSourceTrigger=PropertyChanged}"
    

    Output:

    enter image description here