Search code examples
windows-phone-7listboxwcf-data-servicesodata

WP7.1 - How to refresh ListBox with oData


In my Windows Phone 7.1 application. I have a listbox inside of a pivot control. My listbox populates with data using OData from a web service. I am using the service found at http://services.odata.org/Northwind/Northwind.svc/ for my testing. I am having trouble refreshing the data in the listbox. For example, when the application loads, the app fetches data for OrderIDs 10248 and 10249. Now if the user presses a button in the application bar, I want to fetch records for OrderIDs 10250 and 10251. When I make the call to fetch the data, I don't get any errors from the application, and the data in the UI does not refresh. I understand from my reading that DataServiceCollection implements ObservableCollection which itself implements INotifyPropertChanged, so my UI should just refresh when the collection changes. But this is not the case.

I have tested this in a WPF application using a GridView and the UI refreshes just fine with new data. I understand though that the calls in WPF are not async though. Any help is appreciated.

Below is the code I am using in my ViewModel to fetch the data.

    private NorthwindEntities context;
    private const string svcUri = "http://services.odata.org/Northwind/Northwind.svc/";

    public MainViewModel()
    {
        List<string> nums = new List<string>() { "10248", "10249" };
        GetDataFromService(nums);
    }

    public void GetDataFromService(List<string> zNumbers)
    {
        try
        {
            string partQuery = "Orders()?$filter =";

            if (zNumbers.Count > 0)
            {
                foreach (var item in zNumbers)
                {
                    partQuery += "(OrderID eq " + item + ") or ";
                }

                partQuery = partQuery.Substring(0, partQuery.Length - 3).Trim();
            }

            // Initialize the context for the data service.
            context = new NorthwindEntities(new Uri(svcUri));

            Uri queryUri = new Uri(partQuery, UriKind.Relative);
            trackedCustomers = new DataServiceCollection<Order>(context);
            trackedCustomers.LoadAsync(queryUri);
        }
        catch (DataServiceQueryException ex)
        {
            MessageBox.Show("The query could not be completed:\n" + ex.ToString());
        }
        catch (InvalidOperationException ex)
        {
            MessageBox.Show("The following error occurred:\n" + ex.ToString());
        }
    }

    private DataServiceCollection<Order> trackedCustomers;

    public DataServiceCollection<Order> TrackedCustomers
    {
        get { return trackedCustomers; }
        set
        {
            if (value != trackedCustomers)
            {
                trackedCustomers = value;
                NotifyPropertyChanged("TrackedCustomers");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (null != handler)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

And here is the XAML in my MainPage.xaml

    <Grid x:Name="LayoutRoot" Background="Transparent">
    <!--Pivot Control-->
    <controls:Pivot Title="MY APPLICATION">
        <!--Pivot item one-->
        <controls:PivotItem Header="first">
            <!--Double line list with text wrapping-->
            <ListBox x:Name="FirstListBox" Margin="0,0,-12,0" ItemsSource="{Binding             TrackedCustomers, Mode=OneWay}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                      <StackPanel Margin="0,0,0,17" Width="432" Height="78">
                            <TextBlock Text="{Binding OrderID}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                            <TextBlock Text="{Binding Freight}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
                      </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </controls:PivotItem>          
    </controls:Pivot>
</Grid>

Solution

  • Is there a handler that gets called after LoadAsync is finished? If so, that is when you need to make an assignment to the public property TrackedCustomers.

    Or, possibly change these lines to use the public property:

            trackedCustomers = new DataServiceCollection<Order>(context);
            trackedCustomers.LoadAsync(queryUri);