Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Не обновляется ListBox после обновления элемента 
:(
    Опции темы
Dims
Дата 16.10.2008, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 0
Всего: 11



Я сделал собственный класс 

Код

class NumberStatus
    {
        private String number;
        private Conclusion concl;
        private String message;
...


в котором переопределил метод ToString.

Затем добавляю множество объектов этого типа в ListBox. Параллельно закладываю те же объекты в массив. 

На экране всё отображается правильно.

Далее, в процессе работы меняю message у объектов в массиве. В отладчике проверил -- члены ListBox-а тоже изменяются. Однако, визуально на экране ничего не меняется, отображается первоначальное значение.

Ни Update, ни Refresh, ни Invalidate не помогают.

Только перезакладываение всех элементов заново в ListBox.

Что делать, как заставить ListBox переопросить ToString своих эелемнтов?
PM MAIL   Вверх
diadiavova
Дата 16.10.2008, 21:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Листбокс переопрашивает список при присвоении(или изменении) значения свойства DisplayMember, его и надо переназначить
Код

// Сначала меняем значения элементов, потом пишем
ListBox1.DisplayMamber = "ToString";

Кстати можно специальное свойство придумать, а ToString использовать по назначению.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
diadiavova
Дата 16.10.2008, 21:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Исправлюсь: если значением DisplayMember является имя свойства, отображаться будет значение этого свойства, в ином случае вызывается ToString. Поэтому если нужно отображать то, что выдаёт ToString, можно передавать DisplayMember даже пустую строку.

Это сообщение отредактировал(а) diadiavova - 16.10.2008, 21:54


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Dims
Дата 17.10.2008, 00:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 0
Всего: 11



Дело в том, что отображается всё правильно. Проблема в том, что не происходит обновление отображаемой информации.

Что-то я не совсем понял, что и как мне надо переопределить?
PM MAIL   Вверх
diadiavova
Дата 17.10.2008, 00:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Я понимаю, что слово "переназначить" звучит непонятно. Просто свойству дисплеймембер надо вновь присвоить значение, чтобы обновился вид. Хотябы пустую строку если надо отобразить значение тустринг. Вот это нужно сделать вместо рефрешей всяких
Код

ListBox1.DisplayMamber = "";

или если надо отображать значение какого-либо свойства, то вместо пустой строки - имя свойства. Делать это надо каждый раз для обновления, даже если присваивается одно и то же значение.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
jonie
Дата 17.10.2008, 00:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 22
Всего: 118



надо унаследоваться от INotifyPropertyChanged 
читать тут:http://msdn.microsoft.com/en-us/library/ms743695.aspx
DataMember тут при чем, но косвенно. Вы не уведомляете listbox о происходящих изменениях.
----
UPD: тока там хрнеь написана в одном месте, читать ее надо так:
Код

if(!name.Equals(value)) {
              name = value;
              // Call OnPropertyChanged whenever the property is updated
              OnPropertyChanged("PersonName");
}

это чтобы не заставлять обновлять лишний раз.
---------
UPD1: еще вот это почитать для упрощеия себя жизни http://www.codeplex.com/ActiveSharp

Это сообщение отредактировал(а) jonie - 17.10.2008, 00:33


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
diadiavova
Дата 17.10.2008, 00:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Цитата(jonie @  17.10.2008,  00:28 Найти цитируемый пост)
DataMember тут не при чем

Речь не о DataMember, а о DisplayMember, я этот вариант попробовал - работает, кроме того он подходит для любых типов, а не только собственных.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
jonie
Дата 17.10.2008, 00:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 22
Всего: 118



да сколько хотите. это не будет работать:
Код

    public partial class Form1 : Form
    {
        class Class1
        {
            private string str = "OLD_STRING";

            public string Str
            {
                get { return str; }
                set { str = value; }
            }
        }

        public Form1()
        {
            InitializeComponent();
            listBox1.DisplayMember = "Str";
            listBox1.Items.Add(c);
        }

        private Class1 c = new Class1();

       private void button1_Click(object sender, EventArgs e)
        {
           c.Str = "NEW_STR";
        }
    }


Это сообщение отредактировал(а) jonie - 17.10.2008, 00:40


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
diadiavova
Дата 17.10.2008, 00:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



В таком виде - да. Я говорю об этом.
Код

private void button1_Click(object sender, EventArgs e)
        {
           c.Str = "NEW_STR";
           listBox1.DisplayMember = "Str";
        }



--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
jonie
Дата 17.10.2008, 00:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 22
Всего: 118



да это бред. зачем обновлять ВЕСЬ список ??

вот пример того о чем я говорил
Код

    public partial class Form1 : Form
    {
        class Class1 : INotifyPropertyChanged
        {
            private string str = "OLD_STRING";

            public string Str
            {
                get { return str; }
                set
                {
                    if (!str.Equals(value))
                    {
                        str = value;
                        PropertyChangedEventHandler PropertyChangedTmp = PropertyChanged;
                        if (PropertyChangedTmp != null)
                        {
                            PropertyChangedTmp(this, new PropertyChangedEventArgs("Str"));
                        }
                    }
                }
            }

            public event PropertyChangedEventHandler PropertyChanged;

        }

        public Form1()
        {
            InitializeComponent();
            listBox1.DisplayMember = "Str";

            System.ComponentModel.BindingList<Class1> nl = new System.ComponentModel.BindingList<Class1>();
            nl.Add(c);

            listBox1.DataSource = nl;

        }

        private Class1 c = new Class1();

        private void button1_Click(object sender, EventArgs e)
        {
            c.Str = "NEW_STR";
        }
    }



--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
diadiavova
Дата 17.10.2008, 00:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Цитата(Dims @  16.10.2008,  20:36 Найти цитируемый пост)
Что делать, как заставить ListBox переопросить ToString своих эелемнтов? 

Я всего-навсего ответил на этот вопрос. Просто в форумах стараюсь отвечать на то, о чём меня спрашивают. Думаю пользователю Dims, дополнительная информация тоже не повредит, но я ответил только на вопрос.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Dims
Дата 29.10.2008, 17:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 0
Всего: 11



Цитата(diadiavova @  17.10.2008,  00:17 Найти цитируемый пост)
Делать это надо каждый раз для обновления, даже если присваивается одно и то же значение.

Я понял идею. Тип Лист чувствует, что ему обновили указивку что показывать и тогда переопрашивает. 

Но у меня это почему-то не работает.

Видимо, он сравнивает старое значение и новое и, если они совпадают, то не делает ничего.

Добавлено через 3 минуты и 53 секунды
А можно объяснить пошагово, что делает вот этот код?

Код

PropertyChangedEventHandler PropertyChangedTmp = PropertyChanged;
                        if (PropertyChangedTmp != null)
                        {
                            PropertyChangedTmp(this, new PropertyChangedEventArgs("Str"));
                        }


Зачем мы заводим новую переменную типа PropertyChangedEventHandler? Нельзя было бы переписать так:

Код

                        if (PropertyChanged != null)
                        {
                            PropertyChanged(this, new PropertyChangedEventArgs("Str"));
                        }


Откуда берутся эти типы? Они из стандартной библиотеки?

Добавлено через 9 минут и 8 секунд
И что делает вот это:

PropertyChangedTmp(this, new PropertyChangedEventArgs("Str"));

что такое Str? Это имя свойства?

У меня не работает.

Добавлено через 10 минут и 41 секунду
Если у меня ToString, то что писать?
PM MAIL   Вверх
Dims
Дата 29.10.2008, 18:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 0
Всего: 11



Сделал отдельное свойство, всё равно не работает.



Код

class NumberStatus
    {
        private String number;
        private Conclusion concl;
        private String message;

        public NumberStatus(String number)
        {
            init(number, "");
        }

        public NumberStatus(String number, String message)
        {
            init(number, message);
        }

        private void init(String number, String message)
        {
            this.number = number;
            this.concl = Conclusion.Waiting;
            this.message = message;
        }

        public string Number
        {
            get
            {
                return number;
            }
        }

        public Conclusion Concl
        {
            get
            {
                return concl;
            }
            set
            {
                concl = value;
                PropertyChangedEventHandler PropertyChangedTmp = PropertyChanged;
                if (PropertyChangedTmp != null)
                {
                    PropertyChangedTmp(this, new PropertyChangedEventArgs("ShowText"));
                }
            }
        }

        public string Message {
            get
            {
                return message;
            }
            set
            {
                message = value;
                PropertyChangedEventHandler PropertyChangedTmp = PropertyChanged;
                if (PropertyChangedTmp != null)
                {
                    PropertyChangedTmp(this, new PropertyChangedEventArgs("ShowText"));
                }
            }
        }

        public string ShowText
        {
            get
            {
                string ans = number + " - " + concl.ToString();
                if (message.Length > 0)
                {
                    ans += " - " + message;
                }
                return ans;
            }

        }

        public override string ToString()
        {
            string ans = number + " - " + concl.ToString();
            if (message.Length > 0)
            {
                ans += " - " + message;
            }
            return ans;
        }

        public override int GetHashCode()
        {
            return number.GetHashCode() + concl.GetHashCode() + message.GetHashCode();
        }

        public event PropertyChangedEventHandler PropertyChanged;

    }

    enum  Conclusion : int
    {
        Waiting,
        Progress,
        Success,
        Failed
    }




Добавлено через 1 минуту и 41 секунду
А вот это что такое:

System.ComponentModel.BindingList<Class1> nl = new System.ComponentModel.BindingList<Class1>();

Я этого не делаю.
PM MAIL   Вверх
diadiavova
Дата 29.10.2008, 19:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Цитата(Dims @  29.10.2008,  17:57 Найти цитируемый пост)
Я понял идею. Тип Лист чувствует, что ему обновили указивку что показывать и тогда переопрашивает. 

Но у меня это почему-то не работает.

Видимо, он сравнивает старое значение и новое и, если они совпадают, то не делает ничего.


Он не то чтобы чувствует, просто тот метод, о котором был вопрос, видимо вызывается из сеттера свойства. Он не может у меня работать, а в другом месте не работать. Вариант, описанный для изменения свойства к ToString неприменим. Когда задаётся DisplayMember, у элементов ищется свойство, указанное в значении, если такого свойства нет, то вызывается функция ToString и выводится её значение. Это альтернативный вариант. В приведённом случае проблемы быть не должно, если она есть - желательно бы увидеть кусочек кода.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
jonie
Дата 30.10.2008, 00:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 22
Всего: 118



Цитата

Я понял идею. Тип Лист чувствует, что ему обновили указивку что показывать и тогда переопрашивает. 
паттерн observer в гугле. читать.

Цитата

А можно объяснить пошагово, что делает вот этот код?
Код


  PropertyChangedEventHandler PropertyChangedTmp = PropertyChanged;
                        if (PropertyChangedTmp != null)
                        {
                            PropertyChangedTmp(this, new PropertyChangedEventArgs("Str"));
                        }
Зачем мы заводим новую переменную типа PropertyChangedEventHandler?
это связано с потоковой безопасностью (хотя и тут ее полноценной НЕТ). Когда происходит вызов PropertyChangedTmp(...) вызывается каждый подписанный метод в MulticastDelegate, что может занять значительное время. При этом, чтобы гарантировать, что "никто не отпишется в другом потоке" мы копируем event в копию. Это рекомендуемый способ, описанный в msdn.

Цитата

И что делает вот это:

PropertyChangedTmp(this, new PropertyChangedEventArgs("Str"));

что такое Str? Это имя свойства?
да, это имя свойство, которое мы сейчас меняем.

Цитата

А вот это что такое:

System.ComponentModel.BindingList<Class1> nl = new System.ComponentModel.BindingList<Class1>();

Я этого не делаю.
очень даже зря. BindingList это лист, реализующий observer. На его ListChanging подписывается контрол, отображающий элементы. Сам List в свою очередь подписывается на PropertyChanged каждого своего элемента.



--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0553 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.