Список отказывается обновляться, когда происходят изменения в существующих элементах в BindingList

Я схожу с ума большую часть дня, пытаясь заставить это работать.

У меня есть несколько классов в моем коде. Я постараюсь опубликовать соответствующий код ниже и сделать его как можно короче.

public class ServerSettings
{
    private BindingList<Server> serverList = new BindingList<Server>();

    public ServerSettings()
    {

    }

    private void readSettings()
    {           
        string list = "/Settings/Server";
        XmlNodeList Xn = settings.SelectNodes(list);

        foreach (XmlNode xNode in Xn)
        {
            Server tmpSrv = new Server();
            for (int i=0; i<xNode.ChildNodes.Count; i++)
            {
                if(xNode.ChildNodes[i].Name == "Name")
                    tmpSrv.Name = xNode.ChildNodes[i].InnerText;
                else if(xNode.ChildNodes[i].Name == "Host")
                    tmpSrv.Host = xNode.ChildNodes[i].InnerText;
                else if(xNode.ChildNodes[i].Name == "Username")
                    tmpSrv.Username = xNode.ChildNodes[i].InnerText;
                else if(xNode.ChildNodes[i].Name == "Password")
                    tmpSrv.Password = xNode.ChildNodes[i].InnerText;
            }
            tmpSrv.ID = xNode.Attributes["ID"].Value;
            serverList.Add(tmpSrv);
        }
    }

    public BindingList<Server> getServerList()
    {
        return serverList;
    }

    public void setServer(Server srv, bool isNew)
    {
        if(isNew)
        {
            serverList.Add(srv);
            srvCount++;
        }
        else
        {
            string list = "/Settings/Server[@ID='"+srv.ID+"']";
            XmlNodeList Xn = settings.SelectNodes(list);
            if(Xn.Count == 1)
            {
                XmlNode srvNode = Xn[0];
                for (int i=0; i<srvNode.ChildNodes.Count; i++)
                {
                    if(srvNode.ChildNodes[i].Name == "Name")
                        srvNode.ChildNodes[i].InnerText = srv.Name;
                    else if(srvNode.ChildNodes[i].Name == "Host")
                        srvNode.ChildNodes[i].InnerText = srv.Host;
                    else if(srvNode.ChildNodes[i].Name == "Username")
                        srvNode.ChildNodes[i].InnerText = srv.Username;
                    else if(srvNode.ChildNodes[i].Name == "Password")
                        srvNode.ChildNodes[i].InnerText = srv.Password;
                }
            }
        }

    }
}

И в другом классе формы у меня есть следующая функция, которая вызывается один раз при запуске программы

public void populateServerListBox(ref BindingList<Server> srvList)
    {
        this.serverListBox.DisplayMember = "Name";
        this.serverListBox.DataSource = srvList;
    }

И наконец

public partial class NewServerForm : Form
{
    private bool _isEdit = false;
    private bool isCanceled = true;
    private Server selSrv = null;

    public NewServerForm()
    {
        InitializeComponent();
    }

    void NewServerFormOKBtClick(object sender, EventArgs e)
    {
        isCanceled = false;
        this.Close();
    }

    void NewServerFormCancelBtClick(object sender, EventArgs e)
    {
        isCanceled = true;
        this.Close();
    }

    public bool isEdit
    {
        get
        {
            return _isEdit;
        }
        set
        {
            _isEdit = value;
        }
    }

    public void showForm(ref Server srv)
    {
        selSrv = srv;
        isEdit = true;
        this.newServerFormNameTb.Text = selSrv.Name;
        this.newServerFormHostTb.Text = selSrv.Host;
        this.newServerFormUsernameTb.Text = selSrv.Username;
        this.newServerFormPwdTb.Text = selSrv.Password;
        this.ShowDialog();
    }

    public void showForm()
    {
        selSrv = new Server();
        this.ShowDialog();
    }


    void NewServerFormFormClosing(object sender, FormClosingEventArgs e)
    {           
        if(isCanceled || selSrv == null)
            this.Dispose();
        else if(isEdit && selSrv != null)
        {
            selSrv.Name = this.newServerFormNameTb.Text;
            selSrv.Host = this.newServerFormHostTb.Text;
            selSrv.Username = this.newServerFormUsernameTb.Text;
            selSrv.Password = this.newServerFormPwdTb.Text;
            selSrv.BgwConfigPath = this.newServerFormBgwlocTb.Text;
            isCanceled = true;
            MainProgram.serverSettings.setServer(selSrv, false);
            this.Dispose();
        }
        else if(selSrv != null)
        {
            selSrv.Name = this.newServerFormNameTb.Text;
            selSrv.Host = this.newServerFormHostTb.Text;
            selSrv.Username = this.newServerFormUsernameTb.Text;
            selSrv.Password = this.newServerFormPwdTb.Text;

            MainProgram.serverSettings.setServer(selSrv, true);
            isCanceled = true;
            this.Dispose();
        }
    }
}

Я пытаюсь создать простое меню настроек пользователя для разных серверов, где пользователь может добавлять, удалять или изменять существующие настройки сервера. В форме со списком пользователь нажимает кнопку, которая открывает другую форму с несколькими текстовыми полями, которые пользователь должен заполнить, а затем нажимает кнопку «ОК», чтобы внести изменения.

Эти изменения отражаются в элементах в списке привязок (либо новый элемент, либо обновление существующих). Добавление нового элемента сервера или удаление его из списка привязок немедленно отражается в списке, однако внесение изменений в существующие элементы не приводит к обновлению списка. Закрытие формы, содержащей список, и ее повторное открытие покажет изменение, но я не могу заставить его работать сразу после внесения изменений в список.

Я пробовал вызывать refresh() в списке, resetBindings() в BindingList и некоторых других.

Я что-то упустил здесь?


person Alexandre Thenorio    schedule 15.04.2011    source источник


Ответы (1)


Грязное исправление и известная ошибка Microsoft в списке: всякий раз, когда вам нужно обновить содержимое поля, установите источник данных = null, а затем перепривяжите его.

причина, по которой он не обновляется, заключается в том, что объекты в списке не изменились, и он проверяет только ссылки на объект, а не их содержимое.

[ИЗМЕНИТЬ]

Правильный способ сделать это - реализовать интерфейс INotifyPropertyChanged в вашем классе "Сервер". Позвольте мне дать вам несколько справочных материалов.

http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=VS.80).aspx

http://www.gavaghan.org/blog/2007/07/17/use-inotifypropertychanged-with-bindinglist/

http://www.codeproject.com/KB/cs/BindBetterINotifyProperty.aspx

как обновить элементы списка с помощью INotifyPropertyChanged

person Priyank    schedule 16.04.2011
comment
Спасибо, это решило проблему. Моя типичная удача, моя первая программа, и я уже сталкиваюсь с ошибками. У меня есть еще один вопрос, как мне избежать вызова MainProgram.serverSettings.setServer из newServerForm? Я бы предпочел не ходить вот так и делать это должным образом. - person Alexandre Thenorio; 16.04.2011