Статьи

31 Дней Манго | День № 9: Календарь API

Эта статья является Днем № 9 в серии под названием « 31 Дней Манго» .

Day9-CalendarAPI

Сегодня мы собираемся вернуться в пространство имен Microsoft.Phone.UserData и посмотреть на другой набор данных: календарь. В этой статье мы рассмотрим, как мы можем использовать данные календаря нашего пользователя в наших приложениях и для чего мы будем их использовать.

Важно помнить, что, как и в Contact API, эти данные доступны только для чтения. Мы не будем добавлять новые события в календарь пользователя, но мы сможем увидеть, когда они будут доступны.

Использование данных календаря Windows Phone

Одним из наиболее очевидных способов использования этих данных является создание приложения для планирования. Представьте, что вы создаете приложение для медицинской практики, и одной из функций является опция «назначить встречу». Собирая данные календаря вашего пользователя и сравнивая с доступными расписаниями ваших врачей, вы сможете легко предоставить пользователю возможность встречи, которая идеально подходит для вас обоих.

Другим отличным примером этого будет синхронизация календаря. Например, у нас с женой есть Windows Phone, и каждый из нас использует наш календарь Hotmail для наших мероприятий. С двумя детьми, вы можете себе представить, что происходит много жонглирования, чтобы убедиться, что все доберутся до нужного места. Большинство мероприятий детей запланировано моей женой, и она записывает их в свой календарь. Мой календарь в основном сфокусирован на моих рабочих поездках, собраниях групп пользователей и занятиях спортом. Но календари не разговаривают. Они не синхронизируются. Фактически, единственный найденный нами вариант — добавить оба календаря на оба телефона. Таким образом, я не планирую поездку во время важного семейного события, и она не планирует события, когда я буду вне города.Приложение, которое будет брать два календаря и синхронизировать их, будет замечательным дополнением к моему устройству.

Создание пользовательского интерфейса

Теперь, когда мы поговорили о том, как мы можем использовать эти данные в приложении, давайте посмотрим, как мы на самом деле это делаем. Я предпочитаю начинать с пользовательского интерфейса, потому что он помогает мне понять, какие данные мне понадобятся / понадобятся на моем экране. Для приложения, которое мы создадим в этой статье, мы собираемся использовать элемент управления DatePicker из Silverlight Toolkit для Windows Phone и показать список всех записей календаря, которые есть на устройстве пользователя на этот день.

Если вы не знакомы с набором инструментов Silverlight для Windows Phone, приготовьтесь к тому, что ваш ум просто взорвется. Это бесплатная коллекция элементов управления, доступных на сайте Codeplex для создания приложений Windows Phone. Я обсуждал это в День 21 из 31 Дня Windows Phone , поэтому обязательно ознакомьтесь с этим, прежде чем идти дальше. Есть несколько советов о DatePicker, которые вы не хотите пропустить в этой статье.

В конечном итоге наш интерфейс будет довольно простым. У нас будет DatePicker, позволяющий пользователю выбирать дату, и ListBox, который показывает события календаря на эту дату. Как я упоминал ранее, мы не можем создавать или удалять какие-либо события с помощью этого API, поэтому мы просто читаем и показываем данные пользователю.

В приведенном ниже XAML я снова использовал шаблон приложения Windows Phone по умолчанию, чтобы упростить его выполнение. Единственными изменениями в этом интерфейсе являются добавление DatePicker, ListBox и пары TextBlocks, которые я опишу после кода. Также обратите внимание на запись xmlns: toolkit для Silverlight Toolkit для Windows Phone. Вам понадобится это, чтобы использовать DatePicker.

<phone:PhoneApplicationPage
   x:Class="Day9_CalendarAPI.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"
    xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
   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">

    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="31 DAYS OF MANGO - DAY #9" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="calendar api" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <toolkit:DatePicker x:Name="DateBox" Height="100" Margin="0,37,0,470" ValueChanged="DateBox_ValueChanged" />
            <TextBlock Height="30" HorizontalAlignment="Left" Margin="12,6,0,0" Name="textBlock1" Text="select a date" VerticalAlignment="Top" Width="126" />
            <ListBox x:Name="DateList" Margin="0,143,0,0">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <TextBlock Text="{Binding StartTime}" FontSize="16" />
                            <TextBlock Text="{Binding Subject}" TextWrapping="NoWrap" FontWeight="Bold" FontSize="24" />
                            <TextBlock Text="{Binding Location}" TextWrapping="NoWrap" Margin="0,0,0,15" FontSize="20" Foreground="Gray"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
            <TextBlock Height="30" HorizontalAlignment="Left" Margin="70,107,0,0" Name="MessageText" VerticalAlignment="Top" Width="380" TextAlignment="Right" />
        </Grid>
    </Grid>
</phone:PhoneApplicationPage>
 

DatePicker — удивительно самодостаточный элемент управления. Она автоматически использует сегодняшнюю дату, если вы ее не предоставили (что идеально подходит для нашего приложения), и даже имеет событие для ValueChanged, чтобы мы могли выполнять другой поиск по календарю каждый раз, когда пользователь изменяет значение даты.

Два TextBlocks на самом деле просто украшение, но второй, называемый MessageText, используется, чтобы сообщить пользователю, сколько записей календаря мы получили. Вы увидите это, когда мы попадем в файл с выделенным кодом.

Наконец, есть ListBox. Это немного более сложный пример, чем вчера, но мы привязываем DataTemplate элементов управления к свойствам наших объектов Appointment, которые мы будем получать в нашем коде. Вот быстрый взгляд на интерфейс, который мы создаем:

образ

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

Использование календаря API

Наш пример довольно прост, но на самом деле мы получаем довольно надежный интерфейс для нашего пользователя. Для начала нам нужно сослаться на пространство имен Microsoft.Phone.UserData в наших операторах использования. После этого нам нужно создать новый объект Appointments, который мы будем использовать для доступа к данным календаря на телефоне пользователя.

Вот посмотрите на наш стартовый код:

using System;
using System.Linq;
using Microsoft.Phone.Controls;
using Microsoft.Phone.UserData;

namespace Day9_CalendarAPI
{
    public partial class MainPage : PhoneApplicationPage
    {
        Appointments appointments = new Appointments();

        public MainPage()
        {
            InitializeComponent();
            appointments.SearchCompleted += new EventHandler<AppointmentsSearchEventArgs>(appointments_SearchCompleted);
            appointments.SearchAsync(DateBox.Value.Value, DateBox.Value.Value.AddDays(1), null);
        }

        void appointments_SearchCompleted(object sender, AppointmentsSearchEventArgs e)
        {
            //SEARCH THE CALENDAR!
        }
    }
} 

Как видно из приведенного выше примера, мы создаем обработчик события SearchCompleted, а затем вызываем метод SearchAsync () для выполнения нашего поиска. SearchAsync принимает три параметра:

  • StartDate — значение DateTime, которое указывает на начало нашего поиска. Это инклюзивное значение, поэтому указанное вами время также будет включено в поиск.
  • EndDate — еще одно инклюзивное значение, оно указывает время окончания нашего поиска.
  • State – a user-defined object that you can pass to the search, and it will be returned in the event handler, so that you can identify the individual search.  Simple applications like the one in this article will likely use null for this value.

In our XAML earlier we added a DatePicker to our interface.  You probably noticed that the C# code email above doesn’t really address the user’s selection, nor does it bind the search results to our ListBox control.  Those are the two remaining steps to make our application work like the video from earlier.

For the DatePicker, we need to create an event handler method for the ValueChanged event we created in our XAML.  Because we will likely be calling the SearchAsync() method from several locations in our code, we are just going to have our ValueChanged event method call a new method called SearchCalendar(), where will actually make our SearchAsync() call.  (I removed it from the MainPage() constructor method.)

using System;
using System.Linq;
using Microsoft.Phone.Controls;
using Microsoft.Phone.UserData;

namespace Day9_CalendarAPI
{
    public partial class MainPage : PhoneApplicationPage
    {
        Appointments appointments = new Appointments();

        public MainPage()
        {
            InitializeComponent();
            appointments.SearchCompleted += new EventHandler<AppointmentsSearchEventArgs>(appointments_SearchCompleted);
            SearchCalendar();
        }

        private void SearchCalendar()
        {
            appointments.SearchAsync(DateBox.Value.Value, DateBox.Value.Value.AddDays(1), null);
        }

        private void DateBox_ValueChanged(object sender, DateTimeValueChangedEventArgs e)
        {
            SearchCalendar();
        }

        void appointments_SearchCompleted(object sender, AppointmentsSearchEventArgs e)
        {
            if (e.Results.Count() == 0)
            {
                MessageText.Text = "no events for the selected day";
            }
            else
            {
                MessageText.Text = e.Results.Count() + " events found";
                DateList.ItemsSource = e.Results;
            }
        }
    }
}
 

Finally, you should take a look at the appointments_SearchCompleted() method.  This will get called when our SearchAsync() method completes its search, and contains the data we requested in our search.  In this application, I am checking to see how many records were found, and writing a message to the user in the MessageText textbox.  Finally, if there were records, I am binding the Results of the search to our DateList ListBox that we created in our XAML.

Explaining the Magic of Databinding

For those of you that are getting into XAML development for the first time, the line above:

DateList.ItemsSource = e.Results;

probably seems like there’s some magic going on, and in some ways, there is.  If you look back to our XAML, we had an elaborate ListBox control:

<ListBox x:Name="DateList" Margin="0,143,0,0">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding StartTime}" FontSize="16" />
                <TextBlock Text="{Binding Subject}" TextWrapping="NoWrap" FontWeight="Bold" FontSize="24" />
                <TextBlock Text="{Binding Location}" TextWrapping="NoWrap" Margin="0,0,0,15" FontSize="20" Foreground="Gray"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
 

You should notice that I have 3 TextBlock controls defined inside a DataTemplate for the ListBox.  Each of these TextBlocks have a {Binding} statement for their Text values.  What this means to us, as developers, is that we can choose specific properties of our objects, and bind specific XAML elements to their values.

This isn’t limited to text values, either.  You can bind to nearly any property of a XAML element.  Numbers could be used for Opacity values, colors could be used for Foreground and Fill values.  The only real downside to this style of databinding is that if you change the structure of the objects you’re using (let’s say you remove the Subject from the Appointment object), your page will break because it is expecting that value.  In short though, it’s a great way to pass a collection of objects to a ListBox with a minimal amount of code.

Summary

This article walked you through the steps to create an application that reads the user’s calendar data on their device.  As I mentioned earlier, there’s a wide variety of applications that can use this data effectively, from doctor’s offices to synchronization tools.  How will you use this data?

To download a complete working Windows Phone project that uses all of the code from this article, please click the Download Code button below:

скачать

Tomorrow, we are going to dive into the NetworkInformation class, with an example that will show both the how and the why of this rich piece of data.  See you then!

toolsbutton5

Source: http://www.jeffblankenburg.com/2011/11/09/31-days-of-mango-day-9-calendar-api/