Эта статья является Днем № 14 в серии под названием « 31 день манго» , и была написана приглашенным автором Крисом Вудраффом . С Крисом можно связаться в Твиттере по адресу @cwoodruff . Крис также является ведущим подкаста Deep Fried Bytes , так что постарайтесь это проверить.
Сегодня мы рассмотрим, как использовать данные из канала OData, а также выполнять полные обязанности, которые должны выполнять приложения Windows Phone 7.
Что такое OData?
Официальное заявление для Open Data Protocol (OData) заключается в том, что это веб-протокол для запросов и обновления данных, который предоставляет способ разблокировать ваши данные и освободить их от хранилищ, которые существуют сегодня в приложениях. На самом деле это означает, что мы можем выбирать, сохранять, удалять и обновлять данные из наших приложений так же, как мы годами работали с базами данных SQL. Преимуществом является простота настройки и библиотеки, которые Microsoft создала для нас, разработчиков приложений для Windows Phone 7 Mango. Преимущество заключается в том, что OData имеет стандарт, который позволяет четко понимать данные благодаря метаданным из канала.
За кулисами мы отправляем запросы OData на веб-сервер, на котором подача OData осуществляется через HTTP-вызовы с использованием протокола OData. Вы можете прочитать больше о OData здесь .
Настройка OData для вашего приложения Mango
Теперь с Windows Phone SDK 7.1 у нас есть большой опыт использования OData в наших приложениях. В предыдущей версии Windows Phone SDK 7.0 нам приходилось использовать внешний инструмент для генерации прокси-классов на основе заданного фида OData. Теперь мы встроили поддержку Visual Studio 2010. Чтобы импортировать канал OData, сначала создайте новый проект приложения с поддержкой данных Silverlight для Windows Phone / Windows Phone.
Мы создадим проект с начальным проектом, как показано ниже.
Чтобы импортировать и получить ваш канал OData, доступный из вашего проекта, вам необходимо добавить канал через ссылку «Добавить службу» в Visual Studio 2010.
Вам будет предложено добавить ссылку на службу, и вы введете URL-адрес для канала OData, с которым хотите работать, как показано ниже. Нажмите кнопку «Перейти» для Visual Studio 2010, чтобы собрать информацию о канале, и, наконец, нажмите кнопку ОК, чтобы добавить канал OData в свой проект.
Мы будем использовать для этого проекта канал OData с исторической статистикой бейсбола.
http://www.baseball-stats.info/OData/baseballstats.svc/
Теперь у вас есть сгенерированные прокси-классы, которые позволят вам работать с данными из канала OData, который вы настроили в своем проекте. Добавив канал OData в свой проект, вы также добавили ссылку на сборку System.Data.Services.Client, которая позволит вам работать с каналом OData и данными.
Класс DataServiceCollection
Пространство имен System.Data.Services.Client — это довольно волшебный набор классов, который позволит вам делать много интересных вещей с вашим каналом OData. Мы не будем вдаваться в это пространство имен, кроме DataServiceCollection, но я надеюсь, что вы когда-нибудь изучите эту богатую коллекцию классов.
Класс DataServiceCollection — это класс, который даст вашему проекту и вам, как разработчику, возможность выполнить полный массив работ, используя данные и метаданные вашего канала OData. В вашем распоряжении будут все возможности, основанные на правилах, которые использовались для разработки канала OData. В лучшем случае OData позволит вам выполнить полное CRUD (создание, чтение, обновление, удаление) данных. В этой статье мы рассмотрим только функции чтения DataServiceCollection, чтобы вы могли извлекать и связывать данные в вашем приложении.
Получение данных из канала OData
Мы погрузимся прямо в работу и начнем. В вашем проекте будет файл MainPage.xaml, который был создан в качестве начальной или домашней страницы вашего приложения, как показано ниже. Я обновил свойства ApplicationTitle и PageTitle в XAML, чтобы получить лучшее описание приложения.
Добавьте следующее использование операторов в ваш проект. Это позволит вам использовать DataServiceCollection, а также ссылку на службу, которую мы установили ранее.
using System.Data.Services.Client; using _31DaysMangoOData.ServiceReference1;
Создайте следующие частные переменные в коде MainPage.xaml.cs для MainPage. Это даст вам ссылку на ваш канал OData через переменную _context, коллекцию бейсбольных команд Высшей лиги (_teams), которая существует в канале OData, и, наконец, выбранную команду (_selectedTeam), которая позволит проекту показать список лет выбранная команда играла.
private TeamFranchise _selectedTeam; private BaseballStatsEntities _context;
Нам нужно будет загрузить данные из канала OData, и затем мы реализуем событие Loaded для главной страницы, как показано на рисунке 6.
private void MainPage_Loaded(object sender, RoutedEventArgs e) { _context = new BaseballStatsEntities(new Uri("http://www.baseball-stats.info/OData/baseballstats.svc/")); App.ViewModel.Teams.LoadCompleted += Teams_Loaded; var query = from t in _context.TeamFranchise orderby t.franchName where t.active == "Y" select t; App.ViewModel.Teams.LoadAsync(query); }
Меня спрашивают, зачем нам снова давать URI для канала OData. Разве мы не просто дали это при добавлении ссылки на сервис? Мы сделали, но эта ссылка на URI фида OData была просто для того, чтобы позволить генерацию прокси-классов на основе метаданных из фида. При создании контекста данных нам всегда нужно указывать URI для точки обслуживания фида OData.
Мы инициализируем приватную переменную _teams как универсальный тип DataServiceCollection <T> типа TeamFranchise, который является типом сущности, существующим в фиде OData. Мы связываем обработчик событий _Ceam LoadCompleted с новым методом, который вскоре рассмотрим с именами Teams_Loaded, и, наконец, мы получим наши данные с помощью LINQ. Одна из веских причин для использования класса DataServiceCollection <T> заключается в том, что он позволяет создавать операторы LINQ для запроса данных, а также связывать данные непосредственно с нашими представлениями XAML (мы рассмотрим это в следующем разделе).
Последнее действие, которое мы должны выполнить, — это настроить данные в операторе LINQ. Класс DataServiceCollection будет также асинхронно получать данные для нас. Помните, что так же, как Silverlight, наши проекты Windows Phone 7 Mango должны выполнять все действия асинхронно.
Нам нужен метод, который будет загружать данные в созданный нами DataContext.
private void Teams_Loaded(object sender, LoadCompletedEventArgs e) { if (e.Error == null) { if (App.ViewModel.Teams.Continuation != null) { App.ViewModel.Teams.LoadNextPartialSetAsync(); } else { // Set the data context of the list box control to the team data. this.LayoutRoot.DataContext = App.ViewModel.Teams; } } else { MessageBox.Show(string.Format("We have an error: {0}", e.Error.Message)); } }
Теперь наши бейсбольные команды загружены в переменную _teams и готовы к связыванию. Прежде чем мы покажем, как связать данные с главной страницей проекта, я хочу посмотреть, как также работать со связанными классами сущностей и данными на основе переменной _teams.
Нам нужно изменить MainViewModel, чтобы он содержал данные из канала OData, который был запрошен в MainPage.xaml.cs. Вот код для MainViewModel.cs.
using System; using System.ComponentModel; using System.Data.Services.Client; using _31DaysMangoOData.ServiceReference1; namespace _31DaysMangoOData { public class MainViewModel : INotifyPropertyChanged { public MainViewModel() { this.Teams = new DataServiceCollection<TeamFranchise>(); } /// <summary> /// A collection for ItemViewModel objects. /// </summary> public DataServiceCollection<TeamFranchise> Teams { get; private set; } public bool IsDataLoaded { get; private set; } /// <summary> /// Creates and adds a few ItemViewModel objects into the Items collection. /// </summary> public void LoadData() { this.IsDataLoaded = true; } public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (null != handler) { handler(this, new PropertyChangedEventArgs(propertyName)); } } } }
Привязка данных к вашим представлениям из OData
Теперь мы углубимся в сторону XAML проекта, чтобы показать, как данные из канала OData, расположенного в MainViewModel, связывают ListBox в представлении MainPage, а также с представлением DetailsPage.
MainPage.xaml был связан с MainViewModel, расположенным в файле MainViewModel.cs через DataContext, который мы установили в конструкторе MainPage.
DataContext = App.ViewModel;
Не так много нужно сделать с кодом XAML, который был создан, когда мы запустили проект приложения с привязкой к данным Windows Phone. Мы удалили следующую строку, поскольку у нас нет данных времени разработки.
d:DataContext="{d:DesignData SampleData/MainViewModelSampleData.xaml}"
Нам также нужно изменить Binding of MainListBox просто на {Binding}, так как мы установили следующую строку кода в методе MainPage.xaml.cs Teams_loaded.
this.LayoutRoot.DataContext = App.ViewModel.Teams;
Это будет иметь DataServiceCollection, содержащую бейсбольные команды, которые мы извлекли из команды OData, готовые для использования и связывания в XAML главной страницы.
Ниже приведен источник XAML для главной страницы.
<phone:PhoneApplicationPage x:Class="_31DaysMangoOData.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="True"> <!--Data context is set to sample data above and LayoutRoot contains the root grid where all other page content is placed--> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel contains the name of the application and page title--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text="31 Days of Mango" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="baseball teams" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <!--ContentPanel contains ListBox and ListBox ItemTemplate. Place additional content here--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <ListBox x:Name="MainListBox" Margin="0,0,-12,0" ItemsSource="{Binding}" SelectionChanged="MainListBox_SelectionChanged"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Margin="0,0,0,17" Width="432" Height="78"> <TextBlock Text="{Binding Path=franchName}" TextWrapping="NoWrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Grid> </phone:PhoneApplicationPage>
Когда мы запустим приложение в эмуляторе Windows Phone, вы увидите, что бейсбольные команды теперь отображаются в приложении.
Получение данных выбранной бейсбольной команды для отображения после перехода приложения к DetailPage.xaml очень просто с несколькими строками кода. Мы хотим назначить команду, которая была выбрана в MainPage, а затем связать DataContext DetailsPage с объектом выбранной команды бейсбольной команды в DataServiceCollection, расположенном в MainViewModel. Код для DetailsPage.xaml.cs ниже.
using System.Windows.Navigation; using Microsoft.Phone.Controls; namespace _31DaysMangoOData { public partial class DetailsPage : PhoneApplicationPage { // Constructor public DetailsPage() { InitializeComponent(); } // When page is navigated to set data context to selected item in list protected override void OnNavigatedTo(NavigationEventArgs e) { string selectedIndex = ""; if (NavigationContext.QueryString.TryGetValue("selectedItem", out selectedIndex)) { int index = int.Parse(selectedIndex); DataContext = App.ViewModel.Teams[index]; } } } }
Опять же, код XAML в DetailsPage.xaml очень прост, в том числе изменяется только ApplicationTitle, а PageTitle представляет собой данные, привязанные к свойству franchName выбранной команды. Я хотел показать активную собственность также только для дополнительной информации.
<phone:PhoneApplicationPage x:Class="_31DaysMangoOData.DetailsPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="True"> <!--Data context is set to sample data above and first item in sample data collection below and LayoutRoot contains the root grid where all other page content is placed--> <Grid x:Name="LayoutRoot" Background="Transparent" d:DataContext="{Binding Items[0]}"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel contains the name of the application and page title--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text="31 Days of Mango" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="ListTitle" Text="{Binding franchName}" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <!--ContentPanel contains details text. Place additional content here--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <TextBlock x:Name="ContentText" Text="{Binding active}" TextWrapping="Wrap" Style="{StaticResource PhoneTextNormalStyle}"/> </Grid> </Grid> </phone:PhoneApplicationPage>
Запустив приложение и выбрав бейсбольную команду на главной странице, вы перейдете на страницу с подробностями, где увидите следующее (люблю моих тигров !!).
Резюме
Подводя итог, использовать OData для потребления данных очень просто. Есть еще много функций, которые System.Data.Services.Client и, в частности, DataServiceCollection могут предложить вам как разработчику. Я надеюсь, что вы видели, как вы можете сделать ваши приложения Windows Phone богатыми данными с минимальными усилиями.
Чтобы загрузить весь этот рабочий проект для Visual Studio 2010, нажмите кнопку Загрузить код ниже.
Завтра приглашенный автор Даг Мэйр проведет вас через ProgressBar, чтобы развлечь и проинформировать вашего пользователя о процессе загрузки или длительном процессе. Увидимся позже!
Источник:
http://www.jeffblankenburg.com/2011/11/14/31-days-of-mango-day-14-using-odata/