Спонсор: Microsoft
Опубликован: 21.03.2013 | Доступ: свободный | Студентов: 6315 / 126 | Длительность: 06:49:00
Лабораторная работа 5:

Поиск и общий доступ

< Онлайн-консультация 1 || Лабораторная работа 5: 12

XAML+C#. Практическое занятие №5

Задание: продолжая проект, полученный в результате выполнения четвертого практического задания, добавьте поддержку контрактов поиска и общего доступа в приложение.

  • В качестве подтверждения выполнения лабораторной работы от вас потребуется предоставить скриншот страницы отдельного элемента (ItemDetailPage.xaml) в режиме вызова контракта общего доступа.

ЗАМЕЧАНИЕ: напоминаем, что ваше приложение должно быть уникальным:

  • Использовать в качестве источников данных источники, отличные от тех, которые приводятся в инструкциям к практическим занятиям
  • Внешний вид приложения должен соответствовать выбранной вами тематике приложения (для всех страниц приложения).
  • Политика конфиденциальности (Privacy Policy) должна соответствовать вашему приложению и быть доступна внутри приложения.

Добавление поиска



Пришло время добавить в приложение контракт поиска. Сделать это достаточно просто. Надо добавить в проект новый Item типа Search Contract:

При этом добавится страница отображения поиска, которую я назвал MySearchResultsPage.xaml.

Если после добавления контракта собрать приложение и попытаться по нему искать, отобразится именно эта страница. Причем, поскольку мы не добавили никакой логики отображения — она будет пустая.

Давайте теперь добавим логику, по которой будет происходить поиск. Для простоты мы будем отрабатывать сценарий поиска в уже работающем приложении, предполагая, что данные из RSS находятся в памяти приложения.

Сначала удалим лишнее определения названия приложения со страницы MySearchResultsPage.xaml, у нас эта переменная уже определена в App.xaml:

 <Page.Resources>
      <CollectionViewSource x:Name="resultsViewSource" Source="{Binding Results}"/>
      <CollectionViewSource x:Name="filtersViewSource" Source="{Binding Filters}"/>
      <common:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
       <!-- TODO: Update the following string to be the name of your app -->
        
 </Page.Resources>

Далее, модифицируем класс Filter, который определен в MySearchResultsPage.xaml.cs, так, чтобы он отдавал список Item нашего типа:

private sealed class Filter<T> : MyReader.Common.BindableBase
{
    private String _name;
    private bool _active;
    private List<T> _results;


    public Filter(String name, IEnumerable<T> results, bool active = false)
    {
        this.Name = name;
        this.Active = active;
        this.Results = results.ToList();
    }

    public List<T> Results
    {
        get { return _results; }

        set { if (this.SetProperty(ref _results, value)) this.OnPropertyChanged("Description"); }
    }

    public override String ToString()
    {
        return Description;
    }

    public String Name
    {
        get { return _name; }
        set { if (this.SetProperty(ref _name, value)) this.OnPropertyChanged("Description"); }
    }

    public int Count
    {
        get { return _results.Count; }
    }

    public bool Active
    {
        get { return _active; }
        set { this.SetProperty(ref _active, value); }
    }

    public String Description
    {
        get { return String.Format("{0} ({1})", _name, this.Count); }
    }
}

Не забудьте добавить в блок using директиву:

using MyReader.Data;

Теперь собственно необходимо определить логику поиска в методе LoadState файла MySearchResultsPage.xaml.cs:

var filterList = new List<Filter<RSSDataItem>>(
    from feed in RSSDataSource.AllGroups
    select new Filter<RSSDataItem>(feed.Title,
    feed.Items.Where(item => (item.Title != null && item.Title.Contains(queryText) ||
             (item.Content != null && item.Content.Contains(queryText)))),
              false));

filterList.Insert(0, new Filter<RSSDataItem>("All", filterList.SelectMany(f => f.Results), true));

А в обработчике Filter_SelectionChanged изменить обращение к фильтру в соответсвии с нашими изменениями выше, а также присвоить полученный результат this.DefaultViewModel["Results"] :

 var selectedFilter = e.AddedItems.FirstOrDefault() as Filter<RSSDataItem>;

this.DefaultViewModel["Results"] = selectedFilter.Results;

Если теперь запустить приложение, и воспользоваться чудо-кнопкой поиска, мы сможем увидеть следующее:


При выборе результатов поиска, у нас не происходит перехода на соответствующую страницу записи, поскольку мы не обрабатываем это событие. Давайте добавим этот функционал. Для этого определим обработчик события ItemClick для resultsGridView: :

<GridView>
    x:Name="resultsGridView"
    AutomationProperties.AutomationId="ResultsGridView"
    AutomationProperties.Name="Search Results"
    TabIndex="1"
    Grid.Row="1"
    Margin="0,-238,0,0"
    Padding="110,240,110,46"
    SelectionMode="None"
    IsSwipeEnabled="false"
    IsItemClickEnabled="True"
    ItemsSource="{Binding Source={StaticResource resultsViewSource}}"
    ItemTemplate="{StaticResource StandardSmallIcon300x70ItemTemplate}" 
    ItemClick="resultsGridView_ItemClick">

И в коде:

private void resultsGridView_ItemClick(object sender, ItemClickEventArgs e)
{
    var itemId = ((RSSDataItem)e.ClickedItem).UniqueId;
    this.Frame.Navigate(typeof(ItemDetailPage), itemId);
}

Теперь можно запустить приложение и проверить, что все работает, как ожидается.

Добавление общего доступа

Зарегистрируем обработчик события DataRequested в NavigateTo страницы (и отпишемся от события в NavigateFrom), и реализуем обработчик в котором предоставим системе название поста и текст:

protected override void OnNavigatedTo(NavigationEventArgs e)
  {
      base.OnNavigatedTo(e);
      DataTransferManager.GetForCurrentView().DataRequested += Share_DataRequested;
  }

  protected override void OnNavigatedFrom(NavigationEventArgs e)
  {
      base.OnNavigatedFrom(e);
      DataTransferManager.GetForCurrentView().DataRequested -= Share_DataRequested;
  }

  private void Share_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
  {
      var selectedItem = (RSSDataItem)this.flipView.SelectedItem;

      args.Request.Data.Properties.Title = selectedItem.Title;
      args.Request.Data.Properties.Description = selectedItem.Content;
      args.Request.Data.SetText(selectedItem.Content);      
  }

Запустите приложение перейдите на страницу поста и проверьте, что теперь приложение может передать данные в другие приложения.


На самом деле мы получаем гораздо больше данных для расшаривания в RSS фиде. Это картинка поста, URI поста и т.д. Предлагаю самостоятельно модифицировать код метода добавляния фида, а также сопутствующие классы, чтобы было больше данных. Больше данных – с большим количеством приложений можно поделиться!

< Онлайн-консультация 1 || Лабораторная работа 5: 12
Андрей Милютин
Андрей Милютин

Будьте добры сообщите какой срок проверки заданий и каким способом я буду оповещен!

Данила Слупский
Данила Слупский

К сожалению, я не могу выполнить данную практическую работу в VS 2013 на WIndows 8.1. Код описанных файлов отличается от кода в моем проекте. Как мне быть?