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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Обновление ListBox после десериализации, данные есть, на форме не обновляется 
V
    Опции темы
dAlex
Дата 13.5.2011, 10:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 208
Регистрация: 3.8.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 2



При изменении данных в самой программе ListBox'ы обновляются нормально (добавление item'ов). А если делать десериализацию, то данные в коллекциях появляются, а в связанных с ними листбоксах нет.

Код

//пробовала делать и так
CclistBox.Items.Refresh();
//и так
CclistBox.UpdateLayout();


описаны так
Код

<ListBox Name="CclistBox" ItemsSource="{Binding Cc_collection}" />


Код

public ObservableCollection<double> Cc_collection
{
    get { return Core.Cc_collection; }
    set
    {
        Core.Cc_collection = value;
        NotifyPropertyChanged("Cc_collection");
    }
}   


Это сообщение отредактировал(а) dAlex - 13.5.2011, 10:27
--------------------
eof()
PM WWW ICQ GTalk Jabber   Вверх
jonie
Дата 13.5.2011, 11:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



а как вы делаете десериализацию? При ней создается новый объект, а у вас биндинг на Cc_collection остается таким какой был наверняка..


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


Бывалый
*


Профиль
Группа: Участник
Сообщений: 208
Регистрация: 3.8.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 2



у меня создается новый объект Core, в котором все хранится. Обычные переменные десереализуются на ура и в текстбоксах появляются =)
--------------------
eof()
PM WWW ICQ GTalk Jabber   Вверх
dAlex
Дата 13.5.2011, 12:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 208
Регистрация: 3.8.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 2



а с текстбоксами я делаю так

Код

Chbox.GetBindingExpression(TextBox.TextProperty).UpdateTarget();


и все обновляется

или надо после десериализации очистить листбокс и добавить туда заново все айтемы?

Это сообщение отредактировал(а) dAlex - 13.5.2011, 12:44
--------------------
eof()
PM WWW ICQ GTalk Jabber   Вверх
Brilona
Дата 13.5.2011, 14:28 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 8.7.2008

Репутация: 2
Всего: 3



Я могу ошибаться, но думаю, что нужно использовать NotifyCollectionChanged вместо NotifyPropertyChanged.
PM MAIL ICQ   Вверх
dAlex
Дата 13.5.2011, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 208
Регистрация: 3.8.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 2



пробую =) делаю по аналогии с propertyChanged

Код

private void NotifyCollectionChanged(string info) //что нужно писать в параметре
{
    if (_collectionChanged != null)
           _collectionChanged(this, new CollectionChangeEventArgs(CollectionChangeAction.Refresh, info); //и, соответственно, во втором параметре здесь?
}   



--------------------
eof()
PM WWW ICQ GTalk Jabber   Вверх
Kefir
Дата 13.5.2011, 15:27 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


«Hakuna Matata»
***


Профиль
Группа: Комодератор
Сообщений: 1878
Регистрация: 25.1.2003
Где: Tampere, Suomi

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



dAlex, коллекция, к которой привязываются листбоксы должна реализовывать INotifyCollectionChanged (например ObservableCollection).
PM MAIL WWW Skype   Вверх
Brilona
Дата 13.5.2011, 16:42 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 8.7.2008

Репутация: 2
Всего: 3



Код

public class ItemCollection : INotifyCollectionChanged
{
    ...
    public event NotifyCollectionChangedEventHandler CollectionChanged;
    
    protected void OnCollectionChanged()
    {
        if (CollectionChanged != null)
        {
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }
    }
    ...
}

PM MAIL ICQ   Вверх
dAlex
Дата 16.5.2011, 09:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 208
Регистрация: 3.8.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 2



Всё равно, изначальная коллекция также обновляется, как и было, а свойства - нет

Код

public event NotifyCollectionChangedEventHandler _collectionChanged;
event NotifyCollectionChangedEventHandler INotifyCollectionChanged.CollectionChanged
{
    add { _collectionChanged += value; }
    remove { _collectionChanged -= value; }
}        
private void NotifyCollectionChanged()
{
    if (_collectionChanged != null)
        _collectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace));
}   
public ObservableCollection<double> Cc_collection
{
    get { return Core._Cc_collection; }
    set
    {
        Core._Cc_collection = value;
        NotifyCollectionChanged();
    }
}

Core._Cc_collection обновляется, Cc_collection остается пустым


Это сообщение отредактировал(а) dAlex - 16.5.2011, 09:17
--------------------
eof()
PM WWW ICQ GTalk Jabber   Вверх
-Mikle-
Дата 16.5.2011, 10:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 13
Всего: 59



После десериализации вызовите событие PropertyChanged для свойства "Cc_collection".
CollectionChanged используется, если меняется коллекция в существующем экземпляре коллекции.


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
dAlex
Дата 16.5.2011, 10:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 208
Регистрация: 3.8.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 2



Цитата(-Mikle- @  16.5.2011,  11:04 Найти цитируемый пост)
CollectionChanged используется, если меняется коллекция в существующем экземпляре коллекции. 

это как? например, у меня есть какие-то данные, но нужно их изменить на десериализуемые, это и есть изменение коллекции в существующем экземпляре?
--------------------
eof()
PM WWW ICQ GTalk Jabber   Вверх
-Mikle-
Дата 16.5.2011, 12:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 13
Всего: 59



Нет. Это, например, вы десериализовали (или создали) коллекцию. Затем, при нажатии на кнопку (или еще как-нить) вызываете метод Add (AddRange, Insert, Clear, Remove и т.д.) у коллекции. То есть это когда меняется существующая (уже забинденная) коллекция. Другое дело, если в какой-то момент создается новая коллекция (new) и затем присваивается свойству. В этом случае оповещение должно происходить об изменении свойства (в вашем случае Cc_collection), так как с логической точки зрения коллекция не изменялась (изменилось свойство, которое будет ссылаться на новый экземпляр).

Еще одно важное замечание: любое событие должно вызываться от имени самого объекта, а не от чужого. Биндинги следят за этим и если экземпляр не тот, то игнорируют любое событие об изменении (CollectionChanged, PropertyChanged и т.д.).

В заключении, предлагаю вам новое решение:
1) Уберите все свойства типа Cc_collection (которые просто делегируют значения свойству Core).
2) Оставьте (или объявите, если еще у вас нет) только свойство Core (открытое). Если я правильно понял, то именно ему вы присваиваете результат десериализации, то есть оно у вас рутовое (если нет, поправьте).
3) В его сетере пропишите вызов события PropertyChanged - OnPropertyChanged("Core")
4) Во всех диндингах, вместо, например, ItemsSource="{Binding Cc_collection}" пишите  ItemsSource="{Binding Path=Core.Cc_collection}"

Что получилось теперь, после того как вы десериализуете ваш рутовый объект и присвоите его свойству Core, то автоматически вызовется событие PropertyChanged (пункт 3) и все биндинги обновятся, так как в путях биндингов будет присутствовать часть Core.


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
dAlex
Дата 16.5.2011, 13:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 208
Регистрация: 3.8.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 2



Сделала свойство Core, забиндила на него, прописала ему OnPropertyChanged, но все равно после десериализации пустота. Наверное, дело в
Цитата(-Mikle- @  16.5.2011,  13:38 Найти цитируемый пост)
любое событие должно вызываться от имени самого объекта, а не от чужого

а как вызвать OnPropertyChanged от имени самого объекта?
И еще -  обычные переменные в текстбоксах появляются, почему?


Это сообщение отредактировал(а) dAlex - 16.5.2011, 13:23
--------------------
eof()
PM WWW ICQ GTalk Jabber   Вверх
-Mikle-
Дата 16.5.2011, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 13
Всего: 59



Ох... не видя кода и имея только общее представление о том что у вас, трудно даже пример привести...
Ну ок...

Имеем наш объект:
Код

    public class MyRootData : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private int _myProperty;
        public int MyProperty
        {
            get { return _myProperty; }
            set
            {
                if (_myProperty == value) return;
                _myProperty = value;
                OnPropertyChanged("MyProperty");
            }
        }

        private ObservableCollection<double> _cc_collection;
        public ObservableCollection<double> Cc_collection
        {
            get { return _cc_collection; }
            set
            {
                if (_cc_collection == value) return;
                _cc_collection = value;
                OnPropertyChanged("Cc_collection");
            }
        }
    }


Имеем виндоу:
Код

<Window x:Class="WpfApplication4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <TextBox Text="{Binding Path=Core.MyProperty}" />

        <ListBox ItemsSource="{Binding Path=Core.Cc_collection}" MinHeight="50"/>

        <Button Content="Load Data" Click="Button_Click" />
        <Button Content="Add item to list box" Click="Button_Click_1" />
        <Button Content="Change MyProperty" Click="Button_Click_2" />
    </StackPanel>
</Window>


И имеем код бехинд такой к нему:
Код

    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this; //это для примера
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private MyRootData _core;
        public MyRootData Core
        {
            get { return _core; }
            set
            {
                if (_core == value) return;
                _core = value;
                OnPropertyChanged("Core");
            }
        }

        private void LoadCore()
        {
            // тут можно десериализовать Core.
            // для примера, я его просто создам вручную, так как разницы абсолютно нет.

            var core = new MyRootData();
            core.MyProperty = 35;
            core.Cc_collection = new ObservableCollection<double> { 2.4, 0.788, 3.55 };

            this.Core = core;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            LoadCore();
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            if (Core == null)
                LoadCore();
            Core.Cc_collection.Add(new Random().NextDouble());
        }

        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            if (Core == null)
                LoadCore();
            Core.MyProperty = new Random().Next();
        }
    }


Тут все работает как надо. Свертесь со своим кодом по этому примеру. Надеюсь, что это поможет.


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
dAlex
Дата 16.5.2011, 14:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 208
Регистрация: 3.8.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 2



хм, то есть я зря свойства все перенесла в MyRootData, надо будет исправить...
Сделала как вы сказали, наконец-то свойство Cc_collection обновляется =) но листбокс на форме почему-то все равно пустует 

Код

public class Window1 : INotifyPropertyChanged
{
    private PropertyChangedEventHandler _propertyChanged;
    event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
    {
        add { _propertyChanged += value; }
        remove { _propertyChanged -= value; }
    }
            
    private RobotsBrain Core;
    public RobotsBrain pCore //пришлось пока так назвать, Core используется много где
    {
        get { return Core; }
        set
        {
            if (Core == value) return;
            OnPropertyChanged("pCore");
        }
    }

    void Load()
    {
        XmlSerializer serializer = new XmlSerializer(typeof(RobotsBrain));
        using (StreamReader stream = new StreamReader("appdata.xml"))
            Core = (RobotsBrain)serializer.Deserialize(stream);
    }
}


Код

public partial class RobotsBrain : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    
    .....
    
    private ObservableCollection<double> _Cc_collection = new ObservableCollection<double>();
    public ObservableCollection<double> Cc_collection
    {
        get { return _Cc_collection; }
        set
        {
            if (_Cc_collection == value) return;
            _Cc_collection = value;
            OnPropertyChanged("Cc_collection");
        }
    }
}


Код

<ListBox ItemsSource="{Binding Path=Core.Cc_collection}" />


Это сообщение отредактировал(а) dAlex - 16.5.2011, 14:37
--------------------
eof()
PM WWW ICQ GTalk Jabber   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | WPF и Silverlight | Следующая тема »


 




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


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

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