Подкласс ObservableCollection <T>ведет себя странно (представление дизайна работает, эмулятор нет) - PullRequest
0 голосов
/ 03 марта 2011

У меня странная проблема с ObservableCollection в WP7 . Я пытаюсь реализовать сериализуемую коллекцию. Я нашел хороший пост здесь: http://kentb.blogspot.com/2007/11/serializing-observablecollection.html

Проблема в том, что она не работает на WP7. Если бы это просто не сработало, я собирался искать другие пути.

Но это странно, это работает "почти". В эмуляторе я получаю:

  • Уведомить о моей реализации CurrentItem
  • Обновлен счетчик количества предметов
  • НЕТ уведомлений об обновлениях для привязанного ListBox

[УСТАРЕЛО, я использовал неправильный класс в DesignerContent, глупая ошибка]
В дизайнерском представлении я получаю:

  • Уведомить о моей реализации CurrentItem
  • ПУСТОЙ счет без каких-либо изменений позже
  • РАБОЧИЕ уведомления об обновлениях для привязанного ListBox

Самый простой способ проверить это - загрузить мой тестовый проект здесь:
http://www.filesavr.com/77B1RN0113044J4

Класс, который вы должны посмотреть, это ObsColl в SimpleTest и представление конструктора SerializerTestPage в AppA. Это действительно странно, это может быть вещь Silverlight или проблема WP7.

Кто-нибудь знает, как решить эту проблему, или имеет ссылку на пример для сериализуемой коллекции ObservableCollection для WP7?

Спасибо, Крис

PS: Кросспост здесь, я обновлю оба поста в случае ответов: http://forums.create.msdn.com/forums/p/76981/467546.aspx

[EDIT]
Я нашел обходной путь, используя класс-оболочку. Это может быть не красиво, но работает нормально. Оболочка (код ниже) может быть сериализована обычным способом (с пометкой DataMember), а ListBox может связываться с DataStorage и тогда ведет себя обычным образом.

В настоящее время я реализовал только Add (), потому что это только для тестирования. Возможно, мне следует изменить DataStorage на коллекцию только для чтения для «внешнего использования», в противном случае вы можете совершить ошибку, пытаясь напрямую добавить в DataStorage.

Может быть, все немного запутано, я постараюсь сделать примеры немного лучше и обновлю этот пост, как только у меня появится время

[/ EDIT]

 public class ObsCollStorable<T> : INotifyPropertyChanged where T : class
{
    public ObservableCollection<T> Storage { get; private set; }
    private List<T> _objects;

    [DataMember]
    public List<T> Objects
    {
        get
        {
            return _objects;
        }
        set
        {
            _objects = value;
            Storage = new ObservableCollection<T>();
            foreach (var s in _objects) Storage.Add(s);
        }
    }


    [DataMember]
    public int CurrentIndex { get; set; }


    public T CurrentString
    {
        get
        {
            if (Storage == null) return null;
            if (Storage.Count <= CurrentIndex) return null;
            return Storage[CurrentIndex];
        }
    }



    public ObsCollStorable()
    {
        Objects = new List<T>();
        Storage = new ObservableCollection<T>();
    }

    public void Add(T t)
    {
        Objects.Add(t);
        Storage.Add(Objects.Last());

        CurrentIndex = Objects.Count - 1;
        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(""));
    }


    public event PropertyChangedEventHandler PropertyChanged;
}

1 Ответ

1 голос
/ 03 марта 2011

Я заметил пару вещей.Во-первых, в вашем представлении «Дизайн» класс DataContext отличается от класса времени выполнения.

<d:DesignProperties.DataContext>
    <SimpleTests:SerializerTestSimple/>
</d:DesignProperties.DataContext>

Измените его на:

<d:DesignProperties.DataContext>
    <SimpleTests:SerializerTest/>
</d:DesignProperties.DataContext>

Синхронизируйте представления.Что касается сериализуемой коллекции, я не был уверен, что именно вы делаете, поэтому я удалил ObsColl, потому что кажется ненужным наследовать из коллекции, когда вы просто хотели сериализовать свойство.Почему бы не добавить это свойство в класс View и сериализовать свойство, когда приложение приостанавливается?Я ничего не знаю о WP7, поэтому примите этот совет с учетом моей неопытности.

Следуя этой логике, я сделал следующее:

[DataContract]
public class SerializerTest : INotifyPropertyChanged, INotifyCollectionChanged
{
    private DispatcherTimer _dT;
    public static string Key { get{return typeof (SerializerTest).FullName;} }

    public ObservableCollection<string> Strings { get; private set; }

    [DataMember]
    public string CurrentItem { get; private set; }

    public SerializerTest()
    {
        Strings = new ObservableCollection<string>();
        Strings.CollectionChanged += StringsCollectionChanged;
        CreateTimer();
    }

    private void StringsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        CurrentItem = Strings[Strings.Count - 1];
        OnPropertyChanged("CurrentItem");
    }

    [OnDeserialized]
    public void Init(StreamingContext c)
    {
        CreateTimer();
    }

    private void CreateTimer()
    {
        _dT = new DispatcherTimer();
        _dT.Tick += (a, b) => Strings.Add(DateTime.Now.ToLongTimeString() + Strings.Count);
        _dT.Interval = new TimeSpan(0, 0, 0, 2);
        _dT.Start();
    }

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

    public event NotifyCollectionChangedEventHandler CollectionChanged;
    public void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
    {
        if (CollectionChanged != null)
        {
            CollectionChanged(this, args);
        }
    }
}

И обновил обязательные операторы:

        <TextBlock 
        Foreground="Red"
        Text="{Binding CurrentItem}"
        Grid.Row="0"></TextBlock>

    <TextBlock 
        Foreground="Yellow"
        Text="{Binding Strings.Count}"
        Grid.Row="1"></TextBlock>

    <ListBox 
        Grid.Row="2"
        ItemsSource="{Binding Path=Strings}"></ListBox>
</Grid>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...