Windows Phone 7 数据绑定计时问题

发布于 2024-10-21 07:43:05 字数 3254 浏览 8 评论 0原文

我有一个 Windows Phone 7 应用程序,它有一个可观察集合的本地“数据库”,这些集合持久保存到独立存储中。当应用程序首次运行时,它会检查是否存在任何数据,如果不存在数据,则它从 WCF 服务检索数据并将其加载到可观察集合中。计时器每 10 秒将数据从可观察集合刷新到隔离存储。我只是对应用程序进行原型设计,因此我想我会使用数据绑定在枢轴控件内的一些简单列表中显示可观察集合中的数据。我遇到的问题是,在从 WCF 服务检索数据的初始场景中,有些列表显示其数据,有些则不显示。 (有 6 个列表,似乎一致的是,相同的 2 个列表没有显示其数据)。如果我然后关闭应用程序并重新打开它,那么所有列表都会按预期显示其数据。不同之处在于,现在数据只是从独立存储加载到可观察集合中 - 不必从 WCF 服务中检索它。

保存可观察集合的类看起来像:

public sealed class Database : INotifyPropertyChanged
{
    //Declare Instance
    private static Database instance;// = new Database();
    private static object syncRoot = new Object();

    //Private Constructor
    private Database() 
    {
        Categories = new ObservableCollection<Category>();
        CategoryTypes = new ObservableCollection<CategoryType>();
        Customers = new ObservableCollection<Customer>();
        Tasks = new ObservableCollection<Task>();
        TimePeriods = new ObservableCollection<TimePeriod>();
        RecentTasks = new ObservableCollection<RecentTask>();
    }

    /// <summary>
    /// The entry point into this Database
    /// </summary>
    public static Database Instance
    {
        get
        {
            if (instance == null)
            {
                lock (syncRoot)
                {
                    if (instance == null)
                    {
                        //custom code
                        instance = new Database();
                    }
                }
            }

            return instance;
        }
    }

    #region Properties

    public ObservableCollection<Category> Categories { get; set; }
    public ObservableCollection<CategoryType> CategoryTypes { get; set; }
    public ObservableCollection<Customer> Customers { get; set; }
    public ObservableCollection<Task> Tasks { get; set; }
    public ObservableCollection<TimePeriod> TimePeriods { get; set; }
    public ObservableCollection<RecentTask> RecentTasks { get; set; }.....

看起来这是某种通知或计时问题,但我正在努力追踪它。

我在 Page_Loaded 事件中设置显示数据的页面的数据上下文,如下所示:

this.DataContext = Database.Instance;

列表框之一的 xaml 如下所示:

<ListBox x:Name="AllTasksListBox" 
                     Margin="0,0,-12,0"
                     ItemsSource="{Binding Tasks}"
                     DisplayMemberPath="Name">
</ListBox>

将数据从 WCF 服务加载到可观察集合中的事件之一如下所示:

void OpenReadCompletedTasks(object sender, OpenReadCompletedEventArgs e)
    {
        DataContractSerializer ser = null;

        try
        {
            ser = new DataContractSerializer(typeof(ObservableCollection<Task>));
            Database.Instance.Tasks = ser.ReadObject(e.Result) as ObservableCollection<Task>;
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

此事件是位于数据库类中。

该问题是否可能是与 OpenReadCompleted 事件处理程序有关的某种线程问题?

令人困惑的是,有些列表显示正确,有些则不能。我已经一遍又一遍地检查代码,但找不到列表处理方式之间的任何差异。

关于如何追踪这个问题或者我做错了什么有什么想法吗?

I have a Windows Phone 7 application that has a local "database" of observable collections which are persisted to isolated storage. When the application first runs it checks to see if any data exists, if there is no data then it retrieves the data from a WCF service and loads it into the observable collections. A timer flushes data from the observable collections to isolated storage every 10 seconds. I am just prototyping the application so thought I would display the data from the observable collections in some simple lists within a pivot control using databinding. The problem that I have is that in the initial scenario where data is retrieved from the WCF service some of the lists show up their data and some don't. (There are 6 lists and it seems consistent that the same 2 do not show their data). If I then close the application and re-open it then all the lists show their data as expected. The difference being that now the data is simply loaded into the observable collections from isolated storage - it does not have to be retrieved from the WCF service.

The class that holds the observable collections looks like:

public sealed class Database : INotifyPropertyChanged
{
    //Declare Instance
    private static Database instance;// = new Database();
    private static object syncRoot = new Object();

    //Private Constructor
    private Database() 
    {
        Categories = new ObservableCollection<Category>();
        CategoryTypes = new ObservableCollection<CategoryType>();
        Customers = new ObservableCollection<Customer>();
        Tasks = new ObservableCollection<Task>();
        TimePeriods = new ObservableCollection<TimePeriod>();
        RecentTasks = new ObservableCollection<RecentTask>();
    }

    /// <summary>
    /// The entry point into this Database
    /// </summary>
    public static Database Instance
    {
        get
        {
            if (instance == null)
            {
                lock (syncRoot)
                {
                    if (instance == null)
                    {
                        //custom code
                        instance = new Database();
                    }
                }
            }

            return instance;
        }
    }

    #region Properties

    public ObservableCollection<Category> Categories { get; set; }
    public ObservableCollection<CategoryType> CategoryTypes { get; set; }
    public ObservableCollection<Customer> Customers { get; set; }
    public ObservableCollection<Task> Tasks { get; set; }
    public ObservableCollection<TimePeriod> TimePeriods { get; set; }
    public ObservableCollection<RecentTask> RecentTasks { get; set; }.....

It seems like it is a notification or timing issue of some sort, but I am struggling to track it down.

I set the data context of the page displaying the data as follows in the Page_Loaded event:

this.DataContext = Database.Instance;

The xaml for one of the list boxes looks like:

<ListBox x:Name="AllTasksListBox" 
                     Margin="0,0,-12,0"
                     ItemsSource="{Binding Tasks}"
                     DisplayMemberPath="Name">
</ListBox>

One of the events that loads data from the WCF service into the observable collections looks like:

void OpenReadCompletedTasks(object sender, OpenReadCompletedEventArgs e)
    {
        DataContractSerializer ser = null;

        try
        {
            ser = new DataContractSerializer(typeof(ObservableCollection<Task>));
            Database.Instance.Tasks = ser.ReadObject(e.Result) as ObservableCollection<Task>;
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

This event is located with the Database class.

Is it possible that the issue is a threading issue of some sort to do wiht the OpenReadCompleted event handler?

What is confusing is that some of the lists display correctly and some don't. I've been over and over the code and cannot find any differences between how the lists are handled.

Any thoughts on how to track this down or what I am doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

摘星┃星的人 2024-10-28 07:43:05

我认为问题在于您更新 ObservableCollection 的方式。

当您添加/删除/更改单个条目时,ObservableCollection 将提供通知。

但是,当您替换整​​个集合时,您需要通知侦听器整个集合已更改 - 否则它们将仍然绑定到旧集合 - 例如实现为:

private ObservableCollection<Task> _tasks;
public ObservableCollection<Task> Tasks
{
   get
   {
       return _tasks;
   }
   set
   {
      _tasks = value;
      if (PropertyChanged != null)
          PropertyChanged(this, new PropertyChangedEventArgs("Tasks");
   }
} 

I think the problem is in the way you are updating the ObservableCollection's

The ObservableCollection will provide notifications when you add/remove/change individual entries.

However, when you replace the entire collection then you need to notify listeners that the entire collection has changed - otherwise they will remain bound to the old collections - e.g. implement as:

private ObservableCollection<Task> _tasks;
public ObservableCollection<Task> Tasks
{
   get
   {
       return _tasks;
   }
   set
   {
      _tasks = value;
      if (PropertyChanged != null)
          PropertyChanged(this, new PropertyChangedEventArgs("Tasks");
   }
} 
合久必婚 2024-10-28 07:43:05

为什么每 10 秒刷新一次存储?您只需要一系列事件

  1. 如果在iso存储中获取数据,则转到结束

  2. 为下载列表1异步设置回调

  3. 调用下载列表 1 async

  4. 下载列表 1 的回调 async - 将数据保存到 iso 存储

重复每个列表末尾的步骤 1 到 3

。从 iso 存储加载列表

Why are you flushing to storage every 10 seconds? You just need a sequence of events

  1. If got data in iso store goto end

  2. Setup callback for download list 1 async

  3. call download list 1 async

  4. callback for download list 1 async - save data to iso store

repeat steps 1 to 3 for each list

end. Load lists from iso store

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文