Windows Phone 7 Data Binding Timing Issues
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开发者_StackOverflow社区 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?
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");
}
}
Why are you flushing to storage every 10 seconds? You just need a sequence of events
If got data in iso store goto end
Setup callback for download list 1 async
call download list 1 async
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
精彩评论