Search code examples
c#wpfcomboboxtwo-way-bindingcustom-object

Editing the attributes of WPF Combobox items that is bound to a custom object list


I am having troubles with building a functionality for a wpf combobox that is bound to a list of custom objects in a class that is not in the same scope as the Mainwindow.

Here is a Custom Object class I have designed to store a list of servers with basic details. This is something that is serialized and deserialized to save the information between sessions of the app:

namespace ServerCollection
{
    [Serializable]
    class ServerConfiguration 
    {
        private ObservableCollection<ServerItem> _servers;
        public ObservableCollection<ServerItem> Servers
        {
            get { return _servers; }
            set
            {
                _servers = value;
            }
        }

        [JsonConstructor]
        public ServerConfiguration()
        {
            Servers = new ObservableCollection<ServerItem>();
        }

    }

    [Serializable]
    class ServerItem : INotifyPropertyChanged
    {
        private string _serverName;
        public string ServerName
        {
            get { return _serverName; }
            set 
            { 
                _serverName = value;
                NotifyPropertyChanged(ServerName);
            }
        }

        private string _url;
        public string URL
        {
            get { return _url; }
            set { _url = value; }
        }

        private string _username;
        public string Username
        {
            get { return _username; }
            set { _username = value; }
        }

        private string _password;
        public string Password
        {
            get { return _password; }
            set { _password = value; }
        }

        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public ServerItem()
        {

        }

        [JsonConstructor]
        public ServerItem(string server_name, string server_url, string server_username, string server_password)
        {
            ServerName = server_name;
            URL = server_url;
            Username = server_username;
            Password = server_password;
        }
    }
}

What I want to achieve: I want to bind the "Servers" list to a combobox in the wpf window and be able to add new server items(works fine), Delete server items (works fine) and be able to edit the details of an exisitng server item (having troubles here).

currently, this is how I am binding the cobmbobox to the servers list from code-behind:

private void BindDropdownToServersList()
        {
            servers_dropdown.SelectedIndex = 0;
            servers_dropdown.DataContext = configuration;
            servers_dropdown.ItemsSource = configuration.Servers;
            servers_dropdown.DisplayMemberPath = "ServerName";

        }

The function to handle the editing procedure (clicking commit after editing textbox entries in the window) is as follows:

private void OK_button_Click(object sender, RoutedEventArgs e)
        {
            switch (mode)
            {
                case (ServerInfoMode.Default):
                    {

                    }
                    break;
                case (ServerInfoMode.Adding):
                    {
                        if (!string.IsNullOrEmpty(URL_textBox.Text) && !string.IsNullOrEmpty(Username_textBox.Text) && !string.IsNullOrEmpty(Password_Box.Password) && !string.IsNullOrEmpty(ServerName_textbox.Text))
                        {
                            ServerItem si = new ServerItem(ServerName_textbox.Text, URL_textBox.Text, Username_textBox.Text, Password_Box.Password);

                            configuration.Servers.Add(si);

                            servers_dropdown.SelectedItem = si;

                            mode = ServerInfoMode.Default;
                            HandleServerInfoMode();
                        }
                        else
                        {
                            MessageBox.Show("Please fill all the server details", "check your entry!", MessageBoxButton.OK, MessageBoxImage.Warning);
                        }


                    }
                    break;
                case (ServerInfoMode.Editing):
                    {
                        if (!string.IsNullOrEmpty(URL_textBox.Text) && !string.IsNullOrEmpty(Username_textBox.Text) && !string.IsNullOrEmpty(Password_Box.Password) && !string.IsNullOrEmpty(ServerName_textbox.Text))
                        {

                            ServerItem item = configuration.Servers.Where(i => i == servers_dropdown.SelectedItem).First();

                            item.ServerName = ServerName_textbox.Text;
                            item.URL = URL_textBox.Text;
                            item.Username = Username_textBox.Text;
                            item.Password = Password_Box.Password;

                            servers_dropdown.SelectedItem = item;

                            mode = ServerInfoMode.Default;
                            HandleServerInfoMode();
                        }
                        else
                        {
                            MessageBox.Show("Please fill all the server details", "check your entry!", MessageBoxButton.OK, MessageBoxImage.Warning);
                        }

                    }
                    break;
                case (ServerInfoMode.Deleting):
                    {

                    }
                    break;
            }
        }

The issue I am facing is: When I edit the server name and commit, the items in the dropdown list of the combobox is updated, but the text displayed on the combobox (current selected value) remains to be the old value, even after calling ComboBox.Items.Refresh(); method.

As seen, the new server name enteed in the textbox reflects in the dropdown list, but the value of the selected item is still the old value ("a")

How can I correctly bind the list of servers to the combobox so that I can reflect changes made to the server items and ensure they are correctly updated in the combobox?

Thank you in advance for any help on this issue! Cheers!


Solution

  • try NotifyPropertyChanged(nameof(ServerName)); or NotifyPropertyChanged("ServerName"); instead of NotifyPropertyChanged(ServerName);

    PropertyChanged event required property name. When property name is incorrect, the binding in the view won't update associated value.

    "the items in the dropdown list of the combobox are updated" - they are likely rebuild every time when drop-down is open, so they have the latest value.