我在WP7中的ObservableCollection 有一个奇怪的问题。我正在尝试实现可序列化的集合。我在这里找到了一篇好文章:http://kentb.blogspot.com/2007/11/serializing-observablecollection.html
问题是:它在WP7上不起作用。 如果它根本不起作用,我会寻找其他方法。
但奇怪的是,它“近乎”有效。在模拟器中我得到:
[DEPRECATED,我在DesignerContent中使用了错误的类,愚蠢的错误]
在设计师视图中我得到:
最简单的测试方法是在此下载我的测试项目:
http://www.filesavr.com/77B1RN0113044J4
您需要查看的类是SimpleTest中的ObsColl和AppA中SerializerTestPage的设计视图。 它真的很奇怪,它可能是一个Silverlight的东西,或WP7的问题。
任何人都知道如何解决这个问题,或者链接到WP7的可序列化ObservableCollection的示例?
谢谢, 克里斯
PS:Crosspost在这里,如果答案,我会更新这两个帖子: http://forums.create.msdn.com/forums/p/76981/467546.aspx
[编辑]
我现在找到了一个使用包装类的解决方法。它可能不漂亮,但它可以正常工作。包装器(下面的代码)可以以正常方式序列化(通过标记为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;
}
答案 0 :(得分:1)
我注意到了一些事情。第一个是你的Design视图有一个不同的类提供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>