WP7.1 — Как обновить ListBox с помощью oData

В моем приложении Windows Phone 7.1. У меня есть список внутри элемента управления Pivot. Мой список заполняется данными с использованием OData из веб-службы. Я использую службу, которую можно найти по адресу http://services.odata.org/Northwind/Northwind.svc/ для моего тестирования. У меня возникли проблемы с обновлением данных в списке. Например, когда приложение загружается, приложение извлекает данные для идентификаторов OrderID 10248 и 10249. Теперь, если пользователь нажимает кнопку на панели приложения, я хочу получить записи для идентификаторов OrderID 10250 и 10251. Когда я делаю вызов для получения данных , я не получаю никаких ошибок от приложения, и данные в пользовательском интерфейсе не обновляются. Из моего чтения я понял, что DataServiceCollection реализует ObservableCollection, который сам реализует INotifyPropertChanged, поэтому мой пользовательский интерфейс должен просто обновляться при изменении коллекции. Но это не так.

Я протестировал это в приложении WPF с использованием GridView, и пользовательский интерфейс отлично обновляется с новыми данными. Однако я понимаю, что вызовы в WPF не являются асинхронными. Любая помощь приветствуется.

Ниже приведен код, который я использую в своей ViewModel для получения данных.

    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));
        }
    }

А вот XAML в моем 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>

person UnscrambleApp    schedule 09.08.2012    source источник


Ответы (2)


Есть ли обработчик, который вызывается после завершения LoadAsync? Если это так, тогда вам нужно сделать назначение общедоступному свойству TrackedCustomers.

Или, возможно, измените эти строки, чтобы использовать общедоступное свойство:

        trackedCustomers = new DataServiceCollection<Order>(context);
        trackedCustomers.LoadAsync(queryUri);
person Gambit    schedule 09.08.2012
comment
Большое спасибо. Использование публичного свойства устранило проблему. Я не думал, что решение будет таким простым. Еще раз спасибо. - person UnscrambleApp; 10.08.2012

Проблема в том, что вы меняете бэкэнд-коллекцию trackedCustomers на новый объект, не сообщая пользовательскому интерфейсу, что он меняется. Пользовательский интерфейс привязан к первому экземпляру объекта, и вы выбрасываете этот объект. Вам нужно будет сделать одну из двух вещей

Очистите резервную коллекцию:

trackedCustomers.Clear();
trackedCustomers.LoadAsync(queryUri);

Или используйте открытое свойство

TrackedCustomers= new DataServiceCollection<Order>(context);
TrackedCustomers.LoadAsync(queryUri);
person Shawn Kendrot    schedule 09.08.2012