简体   繁体   中英

How to bind DataGrid in my situation using mvvm (ObservableCollection inside ObservableCollection)

I am under a situation where i have ObservableCollection of "tablegenerateModel" class which further contains ObservableCollection of "column_Data" class,and this "column_Data" class contains 3 UI elements which have to be binded to DataGrid containing three columns. You can copy paste my code if you want,I have written all classes and xaml for you to verify my code So my Model.cs is as follows :

  public class tablegenerateModel {

    public ObservableCollection < column_Data > Column_data_List {
        get;
        set;
    }
    public int NumberOfColumns {
        get;
        set;
    }

    private ICommand _CreatColumnCommand; //THIS IS THE BUTTON EVENT GENERATED WHEN USER PRESS AN INTEGER VALUE IN "NumberOfColumns" AND PRESS "Create" button. So the "Column_data_List" will repeat that many times the value user entered
    ViewModel vm;
    public ICommand CreatColumnCommand {
        get {
            if (_CreatColumnCommand == null) {
                _CreatColumnCommand = new RelayCommand(
                    param => vm = new ViewModel(this)
                );
            }
            return _CreatColumnCommand;
        }
    }
}
public class column_Data {
    public string Column_Name {
        get;
        set;
    }
}

My View Model is:

   public class ViewModel: INotifyPropertyChanged {
    private ObservableCollection < tablegenerateModel > _lb_GlobalList;
    private ObservableCollection < column_Data > _Column_data_List;

    public ObservableCollection < tablegenerateModel > lb_GlobalList {
        get {
            return _lb_GlobalList;
        }
        set {
            if (value != _lb_GlobalList) {
                _lb_GlobalList = value;
                RaisePropertyChanged("lb_GlobalList");
            }
        }
    }

    public ObservableCollection < column_Data > Column_data_List {
        get {
            return _Column_data_List;
        }
        set {
            if (value != _Column_data_List) {
                _Column_data_List = value;
                RaisePropertyChanged("Column_data_List");
            }
        }
    }

    public ICommand ClickCommand

    private bool _canExecute;
    public ViewModel() {
        _canExecute = true;
        lb_GlobalList = new ObservableCollection < tablegenerateModel > ();
        for (int i = 1; i < 6; i++) {
            //Add To it data here
        }
    }

    public ViewModel(tablegenerateModel tablegenerateModels) //IT WILL BE CALLED WHEN BUTTON WILL BE CLICKED (see tablegenerateModel class ICommand for it)
        {
            Column_data_List = new ObservableCollection < column_Data > ();
            for (int i = 1; i < tablegenerateModels.NumberOfColumns; i++) { //Add data here
            }
            MessageBox.Show("The NumberOfColumns value is:" + tablegenerateModels.NumberOfColumns);
        }

}
}

And View is :

 <Window x:Class="PyXgen.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vM="clr-namespace:PyXgen" Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <vM:ViewModel></vM:ViewModel>
    </Window.DataContext>
    <Grid Name="ButtonsContainer">


        <ListBox Grid.Row="1" ItemsSource="{Binding lb_GlobalList}" ScrollViewer.VerticalScrollBarVisibility="Auto" BorderBrush="Gray" Margin="0,30,0,0" Grid.RowSpan="2">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <StackPanel>
                            <Grid Margin="0,2">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="45" />
                                    <RowDefinition Height="45" />
                                    <RowDefinition Height="45" />
                                    <RowDefinition Height="*" />
                                    <RowDefinition Height="*" />
                                    <RowDefinition Height="*" />
                                </Grid.RowDefinitions>

                                <Grid Grid.Row="4">
                                    <StackPanel>
                                        <Grid Margin="0,2">


                                            Grid.Row="0" Width="80px" Height="20px" Margin="20,5,0,0" Name="fname4"/>
                                            <Button Grid.Row="1" Grid.Column="1" Height="25" Width="70" Content="Create" Command="{Binding CreatColumnCommand}" HorizontalAlignment="Center" VerticalAlignment="Center"></Button>
                                        </Grid>
                                    </StackPanel>
                                </Grid>
                                <Grid Margin="0,2" Grid.Row="5">
                                    <DataGrid x:Name="gvSelectedCourses" Grid.Column="1" HorizontalAlignment="Center" ItemsSource="{Binding Column_data_List , Mode=TwoWay}" AutoGenerateColumns="False" Width="450">
                                        <DataGrid.Columns>
                                            <DataGridTextColumn Header="Column Name" Binding="{Binding  ,Mode=TwoWay}" Width="150" />
                                        </DataGrid.Columns>
                                    </DataGrid>
                                </Grid>
                            </Grid>
                        </StackPanel>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

The button click to "_CreatColumnCommand" (in tableGenerateModel class) will invoke the ViewModel contructor passing "this" object to get the entered integer value to repeat DataGrid rows number of times the entered integer value (this integer value is entered in "NumberOfColumns" textbox of same class)

Now problem is how to bind the "_Column_data_List" such that it will Add and Update the DataGrid's row (by the integer value which user have entered in textbox.

Currently when i enter the integer value in textbox and click the "create" button then ViewModel contructor is called with MessageBox popup

 MessageBox.Show("The NumberOfColumns value is:" + tablegenerateModels.NumberOfColumns);

How to bind this "_Column_data_List" to such that it will add or update the DataGrid's row (by the intger value which user have entered in textbox, in the snapshot above).

Could some one help me pleaseeeeeeeeeeeee ?

Update your code as below. You have binded observable collection within the tablegeneratedModel but you are updating one that is on ViewModel.

public ViewModel(tablegenerateModel tablegenerateModels) //IT WILL BE CALLED WHEN BUTTON WILL BE CLICKED (see tablegenerateModel class ICommand for it)
        {
            tablegenerateModels.Column_data_List = new ObservableCollection<column_Data>();
            for (int i = 1; i < tablegenerateModels.NumberOfColumns; i++)
            {
                Column_data_List.Add(lb_col = new column_Data()
                {
                    Column_Name = "ColumnName" + i,
                    Data_Size = i,
                    Data_types = "Double" + i
                });
            }           
            MessageBox.Show("The NumberOfColumns value is:" + tablegenerateModels.NumberOfColumns);
        }

'CreatColumnCommand' is misspellt, but consistently so, so that is not your problem. But your 'CreatColumnCommand` is not in the viewmodel, but in the model. Is that the problem?

In the given situation i must have ObservableCollection inside ObservableCollection but if you see my ViewModel, I am trying to add to the Column_data_List in ViewModel,Whereas i should do it in Model itself (as view will not handle to both lb_GlobalList and Column_data_List). I done it and it could work for me.

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