Click here to Skip to main content
15,894,252 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am new to WPF. I am struggling for a week to add a row in datagrid on a button click.

My datagrid is bound to
ObservableCollection<FilterCriteria> FilterCriteriaList


Sorry for adding such a length code. Being new to WPF, I am not sure what exactly I am missing here. So trying to provide as much information as possible

This is my FilterCriteria class

public class FilterCriteria : INotifyPropertyChanged
    {
        private NORTHWNDEntities context = new NORTHWNDEntities();

        private string columnName;
        public string ColumnName
        {
            get
            {
                return columnName;
            }
            set
            {
                columnName = value;
                RaisePropertyChanged("ColumnName");
            }
        }

        private string _operator;
        public string Operator
        {
            get
            {
                return _operator;
            }
            set
            {
                _operator = value;
                RaisePropertyChanged("Operator");
            }
        }

        private string inputValue;
        public string InputValue
        {
            get
            {
                return inputValue;
            }
            set
            {
                inputValue = value;
                RaisePropertyChanged("InputValue");
            }
        }

        private string selectedTable;
        public string SelectedTable
        {
            get
            {
                return selectedTable;
            }
            set
            {
                selectedTable = value;
                RaisePropertyChanged("SelectedTable");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged([CallerMemberName]string propertyName = "")
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }


This is my ViewModel Code

public class ExportTablesViewModel : INotifyPropertyChanged
    {
        private NORTHWNDEntities context = new NORTHWNDEntities();

        private ObservableCollection<DatabaseTable> tableNameList;
        public ObservableCollection<DatabaseTable> TableNameList
        {
            get
            {
                return tableNameList;
            }
            set
            {
                tableNameList = value;
                RaisePropertyChanged("TableNameList");
            }
        }

        private ObservableCollection<string> selectedTableColumnList;

        public ObservableCollection<string> SelectedTableColumnList
        {
            get
            {
                return selectedTableColumnList;
            }
            set
            {
                selectedTableColumnList = value;
                RaisePropertyChanged("SelectedTableColumnList");
            }
        }


        private ObservableCollection<FilterCriteria> filterCriteriaList;

        public ObservableCollection<FilterCriteria> FilterCriteriaList
        {
            get
            {
                return filterCriteriaList;
            }
            set
            {
                filterCriteriaList = value;
                RaisePropertyChanged("FilterCriteriaList");
            }
        }


        private string selectedTableName;

        public string SelectedTableName
        {
            get
            {
                return selectedTableName;
            }
            set
            {
                selectedTableName = value;
                RaisePropertyChanged("SelectedTableName");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged([CallerMemberName]string propertyName = "")
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }


This is xaml code for the grid:

<DataGrid x:Name="dataGridFilters" CanUserAddRows="True"  ItemsSource="{Binding FilterCriteriaList}" AutoGenerateColumns="False" HorizontalAlignment="Left" Margin="313,31,0,0" VerticalAlignment="Top" Height="261" Width="679">
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="Column">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox x:Name="ComboBoxColumnName" ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.SelectedTableColumnList}" 
                                      SelectedValue="{Binding Path=ColumnName,Mode =TwoWay,UpdateSourceTrigger=PropertyChanged, NotifyOnTargetUpdated=True,NotifyOnSourceUpdated=True}" SelectedValuePath="ColumnName"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn Header="Operator">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox x:Name="TextBoxOperator" Text="{Binding Path=Operator,Mode =TwoWay,UpdateSourceTrigger=PropertyChanged, NotifyOnTargetUpdated=True,NotifyOnSourceUpdated=True}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn Header="Value">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox x:Name="TextBoxInputValue" Text="{Binding Path=InputValue,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, NotifyOnTargetUpdated=True,NotifyOnSourceUpdated=True}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
        <Button x:Name="buttonAddFilter" Content="+" HorizontalAlignment="Left" Margin="958,76,0,0" VerticalAlignment="Top" Width="34" RenderTransformOrigin="0.5,0.5" Click="buttonAddFilter_Click">
        </Button>


On click on the button, I am trying to add the row in the grid. To do that, I'm adding viewModel.FilterCriteriaList.Add(new FilterCriteria()); in buttonAddFilter_Click event. This code add as new row in the datagrid. But when I enter some value in newly added row. It doesn't get added to the FilterCriteriaList collection

Kindly let me know, how to do two way binding for newly added row?

What I have tried:

already explained in question, like how I have defined view model, ObservableCollection, xaml code
Posted
Updated 20-Apr-17 10:26am

1 solution

First off you don't need to raise property changed with an observable collection, its built in. Second, you should avoid using the "new" key word when binding to an observable collection because that breaks the binding. Observable collections raise property changed on clear() and add() events so

1) Declare you bound Observable Collection once
C#
public ObservableCollection<FilterCriteria> FilterCriteriaList { get; set; }


Then in your constructor you can instantiate.
C#
public ExportFiltersViewModel() 
{ 
   FilterCriteriaList = new ObservableCollection<FilterCriteriaList>(); 
};


Next in your view you are not showing two-way
<DataGrid x:Name="dataGridFilters" CanUserAddRows="True"  ItemsSource="{Binding FilterCriteriaList, Mode="Two-Way" }"


Now here is where you should look up the ICommand properties to bind the Button click event to your view model so it should look something like
<Button x:Name="buttonAddFilter" Content="+" HorizontalAlignment="Left" Margin="958,76,0,0" VerticalAlignment="Top" Width="34" RenderTransformOrigin="0.5,0.5" Command="{Binding ButtonClickCommand}">


or if you have your viewmodel referenced in your xaml.cs then on the event just grab your viewmodel and do something like this
C#
FilterCriteria criteria = new FilterCriteria()
{ //populate properties here or however you populate your object
};

vm.FilterCriteriaList.Add(criteria); //This add triggers the INotify in ObservableCollection


Your row should add.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900