2
votes

I am practicing MVVM application and i am beginner, what i am trying to do is, I have 3 rows in a grid, the first row will contain 3 labels and 3 corresponding buttons. And the second row will contain a button to save the data entered in that textboxes in first row. The third row will contain a datagrid with the same number and type of textboxes (three).

Look can be seen here http://prntscr.com/9v2336

The user will enter the data in first row and then he will press save button in second row and then he must find the written information in the corresponding datagrid columns.

My try is here (Entire Code):

View:

<Window x:Class="WpfApplication4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition Height="30"></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0">
            <Grid.RowDefinitions>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <TextBox Grid.Column="1" Grid.Row="0" Text="{Binding TextName}" Height="20" Width="80" HorizontalAlignment="Center"></TextBox>
            <TextBox Grid.Column="1" Grid.Row="1" Text="{Binding RollNumber}"  Height="20" Width="80"></TextBox>
            <TextBox Grid.Column="1" Grid.Row="2" Text="{Binding Class}" Height="20" Width="80"></TextBox>
            <Label Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center">Name</Label>
            <Label Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center">RollNumber</Label>
            <Label Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center">Class</Label>
        </Grid>
        <Grid Grid.Row="1" >
            <Button Width="80" Height="20" Command="{Binding saveStudentRecord}"> Save</Button>
        </Grid>
        <Grid Grid.Row="2">
            <DataGrid ItemsSource="{Binding DGrid}">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Name" Binding="{Binding dgName}" Width="150"></DataGridTextColumn>
                    <DataGridTextColumn Header="Rollnumber" Binding="{Binding dgRollnumber}" Width="150"></DataGridTextColumn>
                    <DataGridTextColumn Header="Class" Binding="{Binding dgClass}" Width="150"></DataGridTextColumn>
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
    </Grid>
</Window>

Model:

 class Model
    {
        private string textName;
        public string TextName
        {
            get { return textName; }
        }

        private string rollNumber;
        public string RollNumber
        {
            get { return rollNumber; }
        }
        private string cclass;
        public string Class
        {
            get { return cclass; }
        }
    }

ViewModel:

   class ViewModel
    {
        public bool canExecute { get; set; }
        private RelayCommand saveStudentRecord; 
        private ObservableCollection<Model> dGrid;
        public ViewModel()
        {

        }

        private void MyAction()
        {
           //What to do here to pass all that data to the datagrid corresponding columns
        }     
    }

Where i have problem ? I have designed the entire body but i am not able to find the logic that how would i assign the entered data in text boxes to corresponding data-grid columns on button click event and binding themusing only MVVM.

1
You need to bind your DataGrid to a collection, perhaps an ObservableCollection and then Update the ObservableCollection in you Command.Ryan Searle

1 Answers

4
votes

Should be simple as adding a new Model to your ObservableCollection<Model> DGrid:

 class ViewModel
    {
        public bool canExecute { get; set; }
        private RelayCommand saveStudentRecord; 
        private ObservableCollection<Model> dGrid;
        public ViewModel()
        {
            dGrid = new ObservableCollection<Model>();
        }

        private void MyAction()
        {
           dGrid.Add(new Model(){
               TextName = valueOfTextTextBox,
               RollNumber = valueOfRollNumberTextBox,
               Class = valueOfClassTextBox
           });
        }     
    }

Thing to remember here: dGrid should be a public property, so you can use Databinding with it, e.g.:

public ObservableCollection<Model> dGrid {
    get;
    private set;
}

EDIT based on the question in commments:

You need to bind the text property of TextBoxes to a property on you ViewModel. As ModelClass holds that kind of info, I would do:

 class ViewModel
    {
        public bool canExecute { get; set; }
        private RelayCommand saveStudentRecord; 
        private ObservableCollection<Model> dGrid;
        public ViewModel()
        {
            dGrid = new ObservableCollection<Model>();
        }

        public Model EditedModel {
            get {
                return _editedModel;
            }
            set {
                _editedModel = value;
                SignalPropertyChanged("EditedModel");
            }
        }

        private void MyAction()
        {
           dGrid.Add(EditedModel);
           EditedModel = new Model();
        }

        void SignalPropertyChanged(string propertyName){
            if(propertyChanged !=null){
                propertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }


    }

Of course now your ViewModel and Model need to implement INotifyPropertyChanged interface to notify view of the changes

class Model : INotifyPropertyChanged
{
    private string textName;
    public string TextName
    {
        get { return textName; }
        set { 
            textName = value; 
            SignalPropertyChanged("TextName");
         }
    }

    private string rollNumber;
    public string RollNumber
    {
        get { return rollNumber; }
        set { 
            rollNumber= value; 
            SignalPropertyChanged("RollNumber");
         }
    }
    private string cclass;
    public string Class
    {
        get { return cclass; }
        set { 
            cclass= value; 
            SignalPropertyChanged("Class");
         }
    }

    public event PropertyChangedEventHandler propertyChanged;
    void SignalPropertyChanged(string propertyName){
        if(propertyChanged !=null){
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

EDIT2 - forgot to add XAML part :) You need to bind the textboxes to a new property

<Window x:Class="WpfApplication4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition Height="30"></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0">
            <Grid.RowDefinitions>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <TextBox Grid.Column="1" Grid.Row="0" Text="{Binding EditedModel.TextName}" Height="20" Width="80" HorizontalAlignment="Center"></TextBox>
            <TextBox Grid.Column="1" Grid.Row="1" Text="{Binding EditedModel.RollNumber}"  Height="20" Width="80"></TextBox>
            <TextBox Grid.Column="1" Grid.Row="2" Text="{Binding EditedModel.Class}" Height="20" Width="80"></TextBox>
            <Label Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center">Name</Label>
            <Label Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center">RollNumber</Label>
            <Label Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center">Class</Label>
        </Grid>
        <Grid Grid.Row="1" >
            <Button Width="80" Height="20" Command="{Binding saveStudentRecord}"> Save</Button>
        </Grid>
        <Grid Grid.Row="2">
            <DataGrid ItemsSource="{Binding DGrid}">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Name" Binding="{Binding dgName}" Width="150"></DataGridTextColumn>
                    <DataGridTextColumn Header="Rollnumber" Binding="{Binding dgRollnumber}" Width="150"></DataGridTextColumn>
                    <DataGridTextColumn Header="Class" Binding="{Binding dgClass}" Width="150"></DataGridTextColumn>
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
    </Grid>
</Window>