Search code examples
wpfdata-bindingobservablecollectioninotifypropertychanged

Combobox bind with ObservableCollection not updating


I'm trying to get a combobox to update when I delete one Item but i can't get it to work.
I'm filling the ObservableCollection form an XML, then I bind it to the combobox, this part works just fine. When i click on the button delete i'am removing from the xml, and iI don't know how to trigger the removal from the observable collecion.

Here's my attempt so far :

ChargementScenario.Xaml

<ComboBox x:Name="cbScenario" ItemsSource="{Binding Scenarios, Mode=TwoWay}" DisplayMemberPath="name" Foreground="Black"
                    HorizontalAlignment="Center" VerticalAlignment="Center" Width="250" Height="40" FontFamily="/GAF-WPF;component/Resources/Font/#Barlow" 
                          Grid.Row="0" Grid.Column="1" SelectionChanged="CbScenario_SelectionChanged">
                </ComboBox>

ChargementScenario.xaml.cs

public partial class pageChargementScenario : Page
    {
        ObservableCollection<Scenario> listScenario = new ObservableCollection<Scenario>();
        public pageChargementScenario()
        {
            InitializeComponent();

            Loaded += pageChargementScenario_Loaded;
        }

        private void pageChargementScenario_Loaded(object sender, RoutedEventArgs e)
        {
            //VERIFICATION DE LA PRESENCE DE SCENARIO 
            ScenarioVM scenarioVM = new ScenarioVM();
            scenarioVM.Scenarios = Scenario.loadListScenario();            

            if (scenarioVM.Scenarios.Count != 0)
            {
                DataContext = scenarioVM;
            }
            else
            {
                cbScenario.IsEnabled = false;
                btnLoadScenario.Visibility = Visibility.Hidden;
                btnDeleteScenario.Visibility = Visibility.Hidden;
            }
        }

private void CbScenario_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var scenario = (Scenario)e.AddedItems[0];
            txtBoxInfoComplementaire.Text = scenario.infoComplementaire;
        }

  private void BtnDeleteScenario_Click(object sender, RoutedEventArgs e)
        {
            DialogResult result = System.Windows.Forms.MessageBox.Show($"Voulez-vous effacer le scenario {cbScenario.Text}", "SUPPRESSION SCENARIO", MessageBoxButtons.YesNo);

            if (result == DialogResult.Yes)
            {
                Scenario.deleteScenario(cbScenario.Text);
            }
        }
}

Scenario.cs

 public class Scenario
    {
        public string name { get; set; }
        public string codeClient { get; set; }
        public string codeAppli { get; set; }
        public string infoComplementaire { get; set; }
        public string modeTelecom { get; set; }
        public string extension { get; set; }
        public string destination { get; set; }
        public string idf { get; set; }
        public string modeEnvoieFtp { get; set; }
        public string typeErreur { get; set; }
        public string partenaire { get; set; }
        public int nombreFichier { get; set; }
        public int intervalleFichier { get; set; }
        public int nombreErreur { get; set; }

        public Scenario()
        {
        }

        public Scenario(string Name, string CodeClient, string CodeAppli, string InfoComplementaire, string ModeTelecom, string Idf, string Partenaire, string Extension, string Destination,
            int NombreFicher, string TypeErreur, int NombreErreur, int IntervalleFichier, string ModeEnvoieFtp)
        {
            name = Name;
            codeClient = CodeClient;
            codeAppli = CodeAppli;
            infoComplementaire = InfoComplementaire;
            modeTelecom = ModeTelecom;
            extension = Extension;
            destination = Destination;
            idf = Idf;
            modeEnvoieFtp = ModeEnvoieFtp;
            typeErreur = TypeErreur;
            partenaire = Partenaire;
            nombreFichier = NombreFicher;
            intervalleFichier = IntervalleFichier;
            nombreErreur = NombreErreur;
        }

        //CHARGEMENT DE LA LISTE DES SCENARIOS
        public static ObservableCollection<Scenario> loadListScenario()
        {
            XDocument xmlScenario = new XDocument();
            if (File.Exists(ConfigurationManager.AppSettings["xmlScenario"]))
            {
                xmlScenario = XDocument.Load(ConfigurationManager.AppSettings["xmlScenario"]);

                //CHARGEMENT DES SCENARIOS
                IEnumerable<Scenario> listeScenario = from scenario in xmlScenario.Descendants("scenario")
                                                      select new Scenario()
                                                      {
                                                          name = (string)scenario.Attribute("nom"),
                                                          codeClient = (string)scenario.Element("codeClient"),
                                                          codeAppli = (string)scenario.Element("codeApplication"),
                                                          infoComplementaire = (string)scenario.Element("informationComplementaire"),
                                                          modeTelecom = (string)scenario.Element("modeTelecom"),
                                                          extension = (string)scenario.Element("extension"),
                                                          destination = (string)scenario.Element("destination"),
                                                          idf = (string)scenario.Element("idf"),
                                                          partenaire = (string)scenario.Element("partenaire"),
                                                          nombreFichier = (int)scenario.Element("nombreFichier"),
                                                          typeErreur = (string)scenario.Element("typeErreur"),
                                                          nombreErreur = (int)scenario.Element("nombreErreur"),
                                                          intervalleFichier = (int)scenario.Element("intervalleFichier"),
                                                          modeEnvoieFtp = (string)scenario.Element("modeEnvoieFtp")
                                                      };

                ObservableCollection<Scenario> collectionScenario = new ObservableCollection<Scenario>(listeScenario);

                return collectionScenario;
            }
            else
            {
                return null;
            }
        }

        public static bool checkDoublon(string scenarioName)
        {
            bool exist = false;

            XDocument xmlScenario = new XDocument();
            xmlScenario = XDocument.Load(ConfigurationManager.AppSettings["xmlScenario"]);

            if (File.Exists(ConfigurationManager.AppSettings["xmlScenario"]))
            {
                exist = xmlScenario.Elements("listScenario").Elements("scenario")
                           .Any(x => x.Attribute("nom").Value == scenarioName);
            }
            return exist;
        }

        public static void saveScenario(Scenario scenario)
        {
            XDocument xmlScenario = new XDocument();

            //CREATION DU XML SI CELUI CI N'EXISTE PAS
            if (!File.Exists(ConfigurationManager.AppSettings["xmlScenario"]))
            {
                xmlScenario = new XDocument(new XElement("listScenario"));
                xmlScenario.Save(ConfigurationManager.AppSettings["xmlScenario"]);
            }

            //CHECK SI LE SCENARIO EXISTE DEJA
            bool scenarioExist = checkDoublon(scenario.name);

            if (scenarioExist)
            {
                MessageBox.Show("UN SCENARIO DU MEME NOM EXISTE DEJA", "ERREUR NOM SCENARIO");
                return;
            }

            //AJOUT DU NOUVEAU SCENARIO
            xmlScenario = XDocument.Load(ConfigurationManager.AppSettings["xmlScenario"]);

            XElement newScenario = new XElement("scenario", new XAttribute("nom", scenario.name),
            new XElement("codeClient", scenario.codeClient),
            new XElement("codeApplication", scenario.codeAppli),
            new XElement("informationComplementaire", scenario.infoComplementaire),
            new XElement("modeTelecom", scenario.modeTelecom),
            new XElement("idf", scenario.idf),
            new XElement("partenaire", scenario.partenaire),
            new XElement("extension", scenario.extension),
            new XElement("destination", scenario.destination),
            new XElement("nombreFichier", scenario.nombreFichier),
            new XElement("typeErreur", scenario.typeErreur),
            new XElement("nombreErreur", scenario.nombreErreur),
            new XElement("intervalleFichier", scenario.intervalleFichier),
            new XElement("modeEnvoieFtp", scenario.modeEnvoieFtp)
            );

            xmlScenario.Root.AddFirst(newScenario);
            xmlScenario.Save(ConfigurationManager.AppSettings["xmlScenario"]);

        }

        public static void deleteScenario(string scenarioName)
        {
            XDocument xmlScenario = new XDocument();
            xmlScenario = XDocument.Load(ConfigurationManager.AppSettings["xmlScenario"]);

            if (File.Exists(ConfigurationManager.AppSettings["xmlScenario"]))
            {
                var elementToRemove = xmlScenario.Elements("listScenario").Elements("scenario")
                           .Where(x => x.Attribute("nom").Value == scenarioName);
                elementToRemove.Remove();

                xmlScenario.Save(ConfigurationManager.AppSettings["xmlScenario"]);
            }
        }


    }

ScenarioVM.cs

    public class ScenarioVM : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
        private ObservableCollection<Scenario> _Scenarios { get; set; }
        public ObservableCollection<Scenario> Scenarios
        {
            get { return _Scenarios; }
            set {
                _Scenarios = value;
                OnPropertyChanged("Scenario");
            }
        }
}

I'm trying to use MVVC but i'm quite new at this so... I don't know what i'm missing...

Thx in advance :)


Solution

  • In order to delete the selected element from the source collection, you need to access the view model, either by casting the DataContext property to the view model type, or by keeping a reference as a class member (e.g. a private field private ScenarioVM scenarioVM;)

    if (result == DialogResult.Yes)
    {
        var selectedScenario = cbScenario.SelectedItem as Scenario;
    
        if (selectedScenario != null)
        {
            var scenarioVM = (ScenarioVM)DataContext;
            scenarioVM.Scenarios.Remove(selectedScenario);
    
            Scenario.deleteScenario(selectedScenario.name);
        }
    }
    

    As a note, your Scenario class should adhere to widely accepted naming conventions, and use PascalCase for property names and camelCase for local variable and method parameter names:

    public class Scenario
    {
        public string Name { get; set; }
        ...
        public Scenario(string name, ...)
        {
            Name = name;
            ...
        }
    }