Resolved Updating Combobox After View model Is Updated

madaxe2020

Member
Joined
Sep 7, 2020
Messages
17
Programming Experience
5-10
in my application I can add / remove Continents to the data grid view , this works fine but if i change a name belonging to an existing continent the change is not reflected in the data grid view


what do i have to change to get the data grid view to update

thanks

Madaxe



XAML:
<DataGrid x:Name="Dgv_ContinentList"
                  AutoGenerateColumns="False"
                  ItemsSource="{Binding   continentsCollection,
                                          Mode=TwoWay,
                                          NotifyOnSourceUpdated=True,
                                          UpdateSourceTrigger=PropertyChanged}"
                    
                  SelectedItem="{Binding  Dgv_SelectedItem,
                                          Mode=TwoWay,
                                          NotifyOnSourceUpdated=True,
                                          UpdateSourceTrigger=PropertyChanged}"
                                  
                  ColumnWidth="*"
                  Background="#FF9F9E9E"
                  Margin="250,125,50,50" >
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding continent_name}" Header="Continent Name" IsReadOnly="True"/>
                <DataGridTextColumn Binding="{Binding modifying_user_id}" Header="Modifying User" IsReadOnly="True"/>
                <DataGridTextColumn Binding="{Binding modifying_date}" Header="Modification Date" IsReadOnly="True"/>
                <DataGridTextColumn Binding="{Binding status}" Header="Status" IsReadOnly="True"/>
            </DataGrid.Columns>
        </DataGrid>

Property:
        private ObservableCollection<Continent> _continentsCollection;
        public ObservableCollection<Continent> continentsCollection
        {
            get => _continentsCollection;
            set
            {
                if (value == _continentsCollection)
                    return;

                _continentsCollection = value;
                base.NotifyPropertyChanged();
            }
        }
 
Last edited:

Sheepings

Senior Programmer
Staff member
Joined
Sep 5, 2018
Messages
1,679
Location
UK
Programming Experience
10+

madaxe2020

Member
Joined
Sep 7, 2020
Messages
17
Programming Experience
5-10
here is my completed code working, the problem was i need to raise a property change event from the model and the viewmodel, im not sure if this is the ebst approach?

Thanks

Madaxe

XAML:
<Window x:Class="WPFBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPFBinding"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Label Content="Continent"
               Margin="30,30,0,0"
               VerticalAlignment="Top" HorizontalAlignment="Left"
               Width="200" Height="25"/>

        <TextBox x:Name="ContinentName"
                 Margin="30,60,0,0"
                 VerticalAlignment="Top" HorizontalAlignment="Left"
                 Width="200" Height="25"
                 Text="{Binding  myContinentName,
                                 Mode=TwoWay,
                                 NotifyOnSourceUpdated=True,
                                 UpdateSourceTrigger=PropertyChanged}"  />

        <Button Content="Create New Continent"
                Command="{Binding Btn_AddNewContinent_Click}"
                CommandParameter="{Binding  ElementName=ContinentName,
                                            Path=Text}"
                Margin="30,125,0,0"
                VerticalAlignment="Top" HorizontalAlignment="Left"
                Width="145" Height="25"/>

        <ComboBox ItemsSource="{Binding continentsNamesList,
                                        Mode=TwoWay,
                                        NotifyOnSourceUpdated=True,
                                        UpdateSourceTrigger=PropertyChanged}"
                  Margin="250,60,0,0"
                  VerticalAlignment="Top" HorizontalAlignment="Left"
                  Width="150" Height="25"  />

        <DataGrid x:Name="Dgv_ContinentList"
                  AutoGenerateColumns="False"
                  ItemsSource="{Binding   continentsCollection,
                                          Mode=TwoWay,
                                          NotifyOnSourceUpdated=True,
                                          UpdateSourceTrigger=PropertyChanged}"
                     
                  SelectedItem="{Binding  Dgv_SelectedItem,
                                          Mode=TwoWay,
                                          NotifyOnSourceUpdated=True,
                                          UpdateSourceTrigger=PropertyChanged}"
                                   
                  ColumnWidth="*"
                  Background="#FF9F9E9E"
                  Margin="250,125,50,50" >
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding continent_name,
                                                      Mode=TwoWay,
                                                      NotifyOnSourceUpdated=True,
                                                      UpdateSourceTrigger=PropertyChanged}"
                                    Header="Continent Name" IsReadOnly="True"/>
                <DataGridTextColumn Binding="{Binding modifying_user_id,
                                                      Mode=TwoWay,
                                                      NotifyOnSourceUpdated=True,
                                                      UpdateSourceTrigger=PropertyChanged}"
                                    Header="Modifying User" IsReadOnly="True"/>
                <DataGridTextColumn Binding="{Binding modifying_date,
                                                      Mode=TwoWay,
                                                      NotifyOnSourceUpdated=True,
                                                      UpdateSourceTrigger=PropertyChanged}"
                                    Header="Modification Date" IsReadOnly="True"/>
                <DataGridTextColumn Binding="{Binding status,
                                                      Mode=TwoWay,
                                                      NotifyOnSourceUpdated=True,
                                                      UpdateSourceTrigger=PropertyChanged}"
                                    Header="Status" IsReadOnly="True"/>
            </DataGrid.Columns>
        </DataGrid>

        <Button Content="Update"
                Command="{Binding Btn_UpdateContinent_Click}"
                    CommandParameter="{Binding  ElementName=ContinentName,
                                                Path=Text}"
                    Margin="30,200,0,0"
                    VerticalAlignment="Top" HorizontalAlignment="Left"
                    Width="145" Height="25" />

        <Button Content="Delete"
                Command="{Binding Btn_DeleteContinent_Click}"
                    CommandParameter="{Binding  ElementName=ContinentName,
                                                Path=Text}"
                    Margin="30,260,0,0"
                    VerticalAlignment="Top" HorizontalAlignment="Left"
                    Width="145" Height="25" />
    </Grid>
</Window>

XAML Code Behind:
using WPFBinding.ViewModels;

namespace WPFBinding
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new DataViewModel();
        }
    }
}

Relay Command:
using System;
using System.Windows.Input;

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

        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
            {
                throw new NullReferenceException("execute");
            }
            else
            {
                this._execute = execute;
                this._canExecute = canExecute;
            }
        }
        public RelayCommand(Action<object> execute) : this(execute, null)
        {

        }
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
        public bool CanExecute(object parameter)
        {
            return this._canExecute == null ? true : this._canExecute(parameter);
        }
        public void Execute(object parameter)
        {
            this._execute.Invoke(parameter);
        }
    }
}

Data View Model:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

using System.Linq;
using WPFBinding.Infrastructure;
using WPFBinding.Models;

using static WPFBinding.Models.Base.ModelBase;

namespace WPFBinding.ViewModels
{
    public class DataViewModel : PropertyChangeBase
    {
        bool _currentModeUpdate = false;
        Continent _originalContinent = null;


        string _myContinentName;
        public string myContinentName{
            get => this._myContinentName;
            set { this._myContinentName = value; NotifyPropertyChanged();}
        }


        Continent _Dgv_SelectedItem;
        public Continent Dgv_SelectedItem {
            get => this._Dgv_SelectedItem;
            set { this._Dgv_SelectedItem = value; base.NotifyPropertyChanged(); this.Dgv_Continents_ItemChanged(value); }
        }


        private ObservableCollection<Continent> _continentsCollection;
        public ObservableCollection<Continent> continentsCollection
        {
            get => _continentsCollection;
            set
            {
                if (value == _continentsCollection)
                    return;

                _continentsCollection = value;
                base.NotifyPropertyChanged();
            }
        }


        private ObservableCollection<string> _continentsNamesList;
        public ObservableCollection<string> continentsNamesList
        {
            get => _continentsNamesList;
            set
            {
                if (value == _continentsNamesList)
                    return;

                _continentsNamesList = value;
                base.NotifyPropertyChanged();
            }
        }



        public RelayCommand Btn_AddNewContinent_Click { get; private set; }
        public RelayCommand Btn_UpdateContinent_Click { get; private set; }

        public RelayCommand Btn_DeleteContinent_Click { get; private set; }
        public DataViewModel()
        {
            this.continentsNamesList = new ObservableCollection<string>() { };
            this.continentsCollection = new ObservableCollection<Continent>() { };

            this.Btn_AddNewContinent_Click = new RelayCommand(AddNewContinent, CanAddNewContinent);
            this.Btn_UpdateContinent_Click = new RelayCommand(UpdateContinent, CanUpdateContinent);
            this.Btn_DeleteContinent_Click = new RelayCommand(DeleteContinent, CanDeleteContinent);
        }


        public void Dgv_Continents_ItemChanged(Continent continent)
        {
            if (continent != null)
            {
                this._currentModeUpdate = true;
                this._originalContinent = continent;
                this.myContinentName = continent.continent_name;
            }
        }


        public void AddNewContinent(object message)
        {
            if (this.continentsNamesList.Contains((string)message) == false)
            {
                Continent continent = new Continent((string)message, 1, DateTime.Now,Status.New);
                this.continentsCollection.Add(continent);
                this.myContinentName = string.Empty;

                UpdateComboboxList();
            }
        }
        public bool CanAddNewContinent(object message)
        {
            bool ReturnBool = false;
            if (string.IsNullOrWhiteSpace((string)message) == false
                && this.continentsNamesList.Contains((string)message) == false
                && this._currentModeUpdate == false)
            {
                this._currentModeUpdate = false;
                this._originalContinent = null;
                ReturnBool = true;
            }
            return ReturnBool;
        }


        public void UpdateContinent(object message)
        {
            if((string)message != this._originalContinent.continent_name)
            {
                Continent continent = (from x in this.continentsCollection where x.continent_name.Equals(this._originalContinent.continent_name) select x).First();
                continent.continent_name = (string)message;
                this.Dgv_SelectedItem = null;
                this._currentModeUpdate = false;
                this.myContinentName = string.Empty;

                UpdateComboboxList();
            }
        }
        public bool CanUpdateContinent(object message)
        {
            bool ReturnBool = false;
            if (this.continentsCollection.Count > 0
                && string.IsNullOrWhiteSpace((string)message) == false
                && this.Dgv_SelectedItem !=null)
            {
                IEnumerable<Continent> Continents= (from x in this.continentsCollection where x.continent_name.Equals((string)message) select x);
                if(Continents.Count() == 0)
                {
                    ReturnBool = true;
                }
            }
            else
            {
                this._currentModeUpdate = false;
                this.Dgv_SelectedItem = null;
            }
            return ReturnBool;
        }


        public void DeleteContinent(object message)
        {
            if (string.IsNullOrWhiteSpace((string)message) == false)
            {
                int index = continentsCollection.ToList().FindIndex(x => x.continent_name == (string)message);  
                this.continentsCollection.RemoveAt(index);
                this.Dgv_SelectedItem = null;
                this._currentModeUpdate = false;
                this.myContinentName = string.Empty;

                UpdateComboboxList();
            }
        }
        public bool CanDeleteContinent(object message)
        {
            bool ReturnBool = false;
            if (this.continentsCollection.Count > 0
                && string.IsNullOrWhiteSpace((string)message) == false
                && this.Dgv_SelectedItem != null
                && continentsCollection.ToList().FindIndex(x => x.continent_name == (string)message) != -1)
            {
               
                ReturnBool = true;
            }
            return ReturnBool;
        }

        private void UpdateComboboxList()
        {        
            this.continentsNamesList = new ObservableCollection<string>(this.continentsCollection.Select(item => item.continent_name).ToList());
        }
    }
}

Model Base:
using WPFBinding.Infrastructure;

namespace WPFBinding.Models.Base
{
    public abstract class ModelBase :  PropertyChangeBase
    {
        public enum Status
        {
            New,
            Deleted,
            Saved,
            Updated        
        }
        public Status status { get; set; }
    }
}

Model:
using System;
using WPFBinding.Models.Base;

namespace WPFBinding.Models
{
    public class Continent : ModelBase
    {
        string _continent_name;
        public string continent_name
        {
            get => this._continent_name;
            set { this._continent_name = value; NotifyPropertyChanged(); }
        }


        int _modifying_user_id;
        public int modifying_user_id
        {
            get => this._modifying_user_id;
            set { this._modifying_user_id = value; NotifyPropertyChanged(); }
        }


        DateTime _modifying_date;
        public DateTime modifying_date
        {
            get => this._modifying_date;
            set { this._modifying_date = value; NotifyPropertyChanged(); }
        }

        public Continent() { }

        public Continent(string ContinentName, int ModifyingUserId, DateTime ModifyingDate, Status Status)
        {
            this.continent_name = ContinentName;
            this.modifying_user_id = ModifyingUserId;
            this.modifying_date = ModifyingDate;
            this.status = Status;
        }
    }
}

Property Change Base:
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace WPFBinding.Infrastructure
{
    public abstract class PropertyChangeBase : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion
    }
}
 
Last edited:

Sheepings

Senior Programmer
Staff member
Joined
Sep 5, 2018
Messages
1,679
Location
UK
Programming Experience
10+
It's always good to see folk resolving their own errors. +1
 
Top Bottom