Разработка приложений для Windows Phone 7

Контакты и календарь в Windows Phone 7

Разбить на страницы
Показывать лекцию целиком

Дополнительные материалы к занятию можно скачать здесь.

Вложенные папки: ContactsAndCalendarTestApp

Ссылки: http://msdn.microsoft.com/en-us/library/hh202972(v=vs.92).aspx

В Windows Phone SDK 7.1 Beta 2 появилась возможность доступа к календарю и контактам пользователя. С помощью календаря можно получать уведомления о заранее запланированных событиях. Из контактов пользователя можно извлекать самую разную информацию, например, электронную почту, телефон, день рождения, фотографию пользователя и так далее. Теперь можно создавать приложения, извлекающие данные из самых разных источников данных. Предположим, часть данных о своих контактах пользователь хранит в самом телефоне, другая часть данных может храниться в сервисах Facebook, Windows Live, Twitter и тому подобное (таблице 34.1). Благодаря технологиям, заложенным в Windows Phone SDK 7.1 Beta 2, можно извлекать данные из подобных источников, руководствуясь разными критериями отбора.

Провайдеры данных, из которых можно извлекать информацию в Windows Phone 7.1
Провайдер данных Имя контакта Изображение контакта Другие данные контакта События календаря
Устройство Windows Phone Да Да Да Да
Социальная сеть Windows Live Да Да Да Да
Windows Live Rolodex Да Да Да Да
Учетные записи MS Exchange (учетные записи из локальной адресной книги, не из глобального списка адресов) Да Да Да Да
Адресная книга мобильного оператора Да Да Да Нет
Facebook Да Да Нет Нет
Агрегированные сети Windows Live (Twitter, LinkedIn и другие) Нет Нет Нет Нет

В предлагаемой работе мы рассмотрим пример, описанный на сайте Microsoft (http://msdn.microsoft.com/en-us/library/hh202972(v=vs.92).aspx) (мы русифицировали интерфейс). Приложение осуществляет поиск информации, хранящейся в контактах пользователя по имени, телефону, электронной почте (рис 34.1) или по дате (рис 34.2).

(рис 34.1) Поиск информации можно осуществлять по имени, телефону и адресу электронной почты (рис 34.2) Поиск по дате

Для начала нам нужно создать с помощью Visual Studio проект Silverlight for Windows Phone 7.1. Назовем приложение ContactsAndCalendarTestApp. Добавьте ссылки на библиотеки Microsoft.Phone.Controls.dll и mscorlib.extensions.dll.

Откройте файл MainPage.xaml и заполните его следующим содержимым:

<phone:PhoneApplicationPage 
    x:Class="ContactsAndCalendarTestApp.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:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:MyApp="clr-namespace:ContactsAndCalendarTestApp"
    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">

    <phone:PhoneApplicationPage.Resources>

        <DataTemplate x:Key="AccountTemplate">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0" Text="{Binding Path=Name, Mode=OneWay}" />
                <TextBlock Grid.Column="1" Text=" account: " />
                <TextBlock Grid.Column="2" Text="{Binding Path=Kind, Mode=OneWay}" />
            </Grid>
        </DataTemplate>

        <MyApp:ContactPictureConverter x:Key="ContactPictureConverter" />

    </phone:PhoneApplicationPage.Resources>

    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">

        <!--Pivot Control-->
        <controls:Pivot Title="Контакты и календарь" >

            <!--Pivot item one-->
            <controls:PivotItem Header="Контакты">

                <StackPanel Height="Auto" Width="Auto" HorizontalAlignment="Stretch" 
                  VerticalAlignment="Stretch" >

                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>

                        <TextBox Grid.Row="0" Grid.ColumnSpan="2" Name="contactFilterString" />
                        <RadioButton Grid.Row="1" Grid.Column="0" Checked="FilterChange"
                         Name="name" Content="Имя" />
                        <RadioButton Grid.Row="1" Grid.Column="1" Checked="FilterChange"
                         Name="phone" Content="Телефон"/>
                        <RadioButton Grid.Row="2" Grid.Column="0" Checked="FilterChange"
                         Name="email" Content="email"/>
                        <Button Grid.Row="2" Grid.Column="1" Content="Поиск"
                         Click="SearchContacts_Click" />
                    </Grid>

                    <TextBlock Name="ContactResultsLabel" Text="Поиск контактов" TextWrapping="Wrap" Margin="12,0,0,0" />

                    <ListBox Name="ContactResultsData" ItemsSource="{Binding}" Tap="ContactResultsData_Tap"
                     Height="300" Margin="24,0,0,0" >
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal" >
                                    <Border BorderThickness="2" HorizontalAlignment="Left" VerticalAlignment="Center"
                                     BorderBrush="{StaticResource PhoneAccentBrush}" >
                                        <Image Source="{Binding Converter={StaticResource ContactPictureConverter}}" Width="48"
                                         Height="48" Stretch="Fill"  />
                                    </Border>
                                    <TextBlock Name="ContactResults" Text="{Binding Path=DisplayName, Mode=OneWay}"
                                     FontSize="{StaticResource PhoneFontSizeExtraLarge}" Margin="18,8,0,0" />
                                </StackPanel>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>

                </StackPanel>
            </controls:PivotItem>


            <!--Pivot item two-->
            <controls:PivotItem Header="Учетные записи">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>

                    <StackPanel Grid.Row="0" >

                        <TextBlock Text="Учетная запись контакта" Foreground="{StaticResource PhoneAccentBrush}" 
                        Style="{StaticResource PhoneTextLargeStyle}" />
                        <ListBox Name="ContactAccounts" ItemsSource="{Binding}" ItemTemplate="{StaticResource AccountTemplate}" 
                        Height="200" Margin="24,0,0,0" />
                    </StackPanel>

                    <StackPanel Grid.Row="1" >

                        <TextBlock Text="Контакты событий" Foreground="{StaticResource PhoneAccentBrush}" 
                        Style="{StaticResource PhoneTextLargeStyle}" />
                        <ListBox Name="CalendarAccounts" ItemsSource="{Binding}" ItemTemplate="{StaticResource AccountTemplate}" 
                        Height="200" Margin="24,0,0,0" />
                    </StackPanel>
                </Grid>
            </controls:PivotItem>


            <!--Pivot item three-->
            <controls:PivotItem Header="События">
                <StackPanel Height="Auto" Width="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >

                    <TextBlock Text="События между" Foreground="{StaticResource PhoneAccentBrush}" />

                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>

                        <TextBlock Grid.Row="0" Grid.Column="0" Text="Дата начала" />
                        <TextBlock Grid.Row="0" Grid.Column="1" Text="Дата завершения" />
                        <TextBlock Grid.Row="1" Grid.Column="0" Text="placeholder" Name="StartDate" />
                        <TextBlock Grid.Row="1" Grid.Column="1" Text="placeholder" Name="EndDate" />
                        <Button Grid.Row="2" Grid.ColumnSpan="2" Content="search" 
                        Click="SearchAppointments_Click" HorizontalAlignment="Center" />
                    </Grid>

                    <TextBlock Name="AppointmentResultsLabel" Text="Поиск событий" TextWrapping="Wrap" />

                    <ListBox Name="AppointmentResultsData" ItemsSource="{Binding}" 
                    Tap="AppointmentResultsData_Tap" Height="400"  ScrollViewer.ManipulationMode="Control" Margin="24,0,0,0" >
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Path=Subject, Mode=OneWay}"
                                  FontSize="{StaticResource PhoneFontSizeExtraLarge}" />
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </StackPanel>
            </controls:PivotItem>
        </controls:Pivot>
    </Grid>
</phone:PhoneApplicationPage>
    

Далее, откройте файл кода MainPage.xaml.cs и введите следующий код:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Microsoft.Phone.Controls;
using Microsoft.Phone.UserData;

namespace ContactsAndCalendarTestApp
{
    public partial class MainPage : PhoneApplicationPage
    {
        FilterKind contactFilterKind = FilterKind.None;

        // Constructor
        public MainPage()
        {
            InitializeComponent();

            name.IsChecked = true;

            ContactAccounts.DataContext = (new Contacts()).Accounts;
            CalendarAccounts.DataContext = (new Appointments()).Accounts;
        }


        //-------------------------------------------------------------------------------
        //-- Contact Methods
        //-------------------------------------------------------------------------------
        private void SearchContacts_Click(object sender, RoutedEventArgs e)
        {
            ContactResultsLabel.Text = "Загружаю результаты ...";
            ContactResultsData.DataContext = null;

            Contacts cons = new Contacts();

            cons.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(Contacts_SearchCompleted);

            cons.SearchAsync(contactFilterString.Text, contactFilterKind, "Contacts Test #1");
        }


        void Contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
        {
            //MessageBox.Show(e.State.ToString());

            try
            {
                //Bind the results to the listbox that displays them in the UI
                ContactResultsData.DataContext = e.Results;
            }
            catch (System.Exception)
            {
                //That's okay, no results
            }

            if (ContactResultsData.Items.Count > 0)
            {
                ContactResultsLabel.Text = "Результаты (Раскройте подробности ...)";
            }
            else
            {
                ContactResultsLabel.Text = "Ничего не найдено";
            }
        }


        private void FilterChange(object sender, RoutedEventArgs e)
        {
            String option = ((RadioButton)sender).Name;

            InputScope scope = new InputScope();
            InputScopeName scopeName = new InputScopeName();

            switch (option)
            {
                case "name":
                    contactFilterKind = FilterKind.DisplayName;
                    scopeName.NameValue = InputScopeNameValue.Text;
                    break;

                case "phone":
                    contactFilterKind = FilterKind.PhoneNumber;
                    scopeName.NameValue = InputScopeNameValue.TelephoneNumber;
                    break;

                case "email":
                    contactFilterKind = FilterKind.EmailAddress;
                    scopeName.NameValue = InputScopeNameValue.EmailSmtpAddress;
                    break;

                default:
                    contactFilterKind = FilterKind.None;
                    break;
            }

            scope.Names.Add(scopeName);
            contactFilterString.InputScope = scope;
            contactFilterString.Focus();
        }


        private void ContactResultsData_Tap(object sender, GestureEventArgs e)
        {
            App.con = ((sender as ListBox).SelectedValue as Contact);

            NavigationService.Navigate(new Uri("/ContactDetails.xaml", UriKind.Relative));
        }


        //-------------------------------------------------------------------------------
        //-- Appointment Methods
        //-------------------------------------------------------------------------------
        private void SearchAppointments_Click(object sender, RoutedEventArgs e)
        {
            AppointmentResultsLabel.Text = "Загружаю результаты ...";
            AppointmentResultsData.DataContext = null;
            Appointments appts = new Appointments();

            appts.SearchCompleted += new EventHandler<AppointmentsSearchEventArgs>(Appointments_SearchCompleted);

            DateTime start = new DateTime();
            start = DateTime.Now;
            //MessageBox.Show(start.ToLongDateString());

            DateTime end = new DateTime();
            end = start.AddDays(7);
            //MessageBox.Show(end.ToLongDateString());

            appts.SearchAsync(start, end, 20, "Appointments Test #1");
        }


        void Appointments_SearchCompleted(object sender, AppointmentsSearchEventArgs e)
        {
            //MessageBox.Show(e.State.ToString());

            StartDate.Text = e.StartTimeInclusive.ToShortDateString();
            EndDate.Text = e.EndTimeInclusive.ToShortDateString();

            try
            {
                //Bind the results to the listbox that displays them in the UI
                AppointmentResultsData.DataContext = e.Results;
            }
            catch (System.Exception)
            {
                //That's okay, no results
            }

            if (AppointmentResultsData.Items.Count > 0)
            {
                AppointmentResultsLabel.Text = "Результаты (Нажмите для получения деталей...)";
            }
            else
            {
                AppointmentResultsLabel.Text = "Ничего не найдено";
            }
        }


        private void AppointmentResultsData_Tap(object sender, GestureEventArgs e)
        {
            App.appt = ((sender as ListBox).SelectedValue as Appointment);

            NavigationService.Navigate(new Uri("/AppointmentDetails.xaml", UriKind.Relative));
        }
    }//End page class


    //-------------------------------------------------------------------------------
    //-- Contact Photo Converter
    //-------------------------------------------------------------------------------
    public class ContactPictureConverter : System.Windows.Data.IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            Contact c = value as Contact;
            if (c == null) return null;

            System.IO.Stream imageStream = c.GetPicture();
            if (null != imageStream)
            {
                return Microsoft.Phone.PictureDecoder.DecodeJpeg(imageStream);
            }
            return null;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }//End converter class


}//End namespace
    

Далее, необходимо открыть файл App.xaml.cs и заполнить его следующим содержимым:

using System.Windows;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace ContactsAndCalendarTestApp
{
    public partial class App : Application
    {
        public static Microsoft.Phone.UserData.Contact con;
        public static Microsoft.Phone.UserData.Appointment appt;

        /// <summary>
        /// Provides easy access to the root frame of the Phone Application.
        /// </summary>
        /// <returns>The root frame of the Phone Application.</returns>
        public PhoneApplicationFrame RootFrame { get; private set; }

        /// <summary>
        /// Constructor for the Application object.
        /// </summary>
        public App()
        {
            // Global handler for uncaught exceptions. 
            UnhandledException += Application_UnhandledException;

            // Standard Silverlight initialization
            InitializeComponent();

            // Phone-specific initialization
            InitializePhoneApplication();

            // Show graphics profiling information while debugging.
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // Display the current frame rate counters.
                //Application.Current.Host.Settings.EnableFrameRateCounter = true;

                // Show the areas of the app that are being redrawn in each frame.
                //Application.Current.Host.Settings.EnableRedrawRegions = true;

                // Enable non-production analysis visualization mode, 
                // which shows areas of a page that are handed off to GPU with a colored overlay.
                //Application.Current.Host.Settings.EnableCacheVisualization = true;

                // Disable the application idle detection by setting the UserIdleDetectionMode property of the
                // application's PhoneApplicationService object to Disabled.
                // Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run
                // and consume battery power when the user is not using the phone.
                PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
            }

        }

        // Code to execute when the application is launching (eg, from Start)
        // This code will not execute when the application is reactivated
        private void Application_Launching(object sender, LaunchingEventArgs e)
        {
        }

        // Code to execute when the application is activated (brought to foreground)
        // This code will not execute when the application is first launched
        private void Application_Activated(object sender, ActivatedEventArgs e)
        {
        }

        // Code to execute when the application is deactivated (sent to background)
        // This code will not execute when the application is closing
        private void Application_Deactivated(object sender, DeactivatedEventArgs e)
        {
        }

        // Code to execute when the application is closing (eg, user hit Back)
        // This code will not execute when the application is deactivated
        private void Application_Closing(object sender, ClosingEventArgs e)
        {
        }

        // Code to execute if a navigation fails
        private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // A navigation has failed; break into the debugger
                System.Diagnostics.Debugger.Break();
            }
        }

        // Code to execute on Unhandled Exceptions
        private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        {
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // An unhandled exception has occurred; break into the debugger
                System.Diagnostics.Debugger.Break();
            }
        }

        #region Phone application initialization

        // Avoid double-initialization
        private bool phoneApplicationInitialized = false;

        // Do not add any additional code to this method
        private void InitializePhoneApplication()
        {
            if (phoneApplicationInitialized)
                return;

            // Create the frame but don't set it as RootVisual yet; this allows the splash
            // screen to remain active until the application is ready to render.
            RootFrame = new PhoneApplicationFrame();
            RootFrame.Navigated += CompleteInitializePhoneApplication;

            // Handle navigation failures
            RootFrame.NavigationFailed += RootFrame_NavigationFailed;

            // Ensure we don't initialize again
            phoneApplicationInitialized = true;
        }

        // Do not add any additional code to this method
        private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
        {
            // Set the root visual to allow the application to render
            if (RootVisual != RootFrame)
                RootVisual = RootFrame;

            // Remove this handler since it is no longer needed
            RootFrame.Navigated -= CompleteInitializePhoneApplication;
        }

        #endregion
    }
}
    

Для нашего приложения понадобятся также файлы AppointmentDetails.xaml (AppointmentDetails.xaml.cs) и ContactDetails.xaml (ContactDetails.xaml.cs). Их нужно создать выполнив следующую последовательность действий: Solution Explorer -> Add -> New Item -> Windows Phone Portrait Page -> AppointmentDetails.xaml (ContactDetails.xaml) и Solution Explorer -> Add -> New Item -> Code File -> AppointmentDetails.xaml.cs (ContactDetails.xaml.cs).

Первые два файла для отображения результатов поиска по дате, вторые два - по контактной информации.

Итак, содержимое файла AppointmentDetails.xaml:

<phone:PhoneApplicationPage 
    x:Class="ContactsAndCalendarTestApp.AppointmentDetails"
    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"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
    shell:SystemTray.IsVisible="True">

    <phone:PhoneApplicationPage.Resources>

        <DataTemplate x:Key="AttendeeTemplate">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0" Text="{Binding Path=DisplayName,
                 Mode=OneWay}" TextWrapping="Wrap" />
                <TextBlock Grid.Column="1" Text=":  " />
                <TextBlock Grid.Column="2" Text="{Binding Path=EmailAddress,
                 Mode=OneWay}" TextWrapping="Wrap" />
            </Grid>
        </DataTemplate>
    </phone:PhoneApplicationPage.Resources>


    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <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,6">
            <TextBlock x:Name="ApplicationTitle" Text="Контакты и календарь"
             Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="Подробности" Margin="9,-7,0,0"
             Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <TextBlock Grid.Row="1" Text="{Binding Path=Subject, Mode=OneWay}"
         Foreground="{StaticResource PhoneAccentBrush}" FontSize="{StaticResource PhoneFontSizeExtraLarge}"
          TextWrapping="Wrap" />

        <!--ContentPanel - place additional content here-->
        <ScrollViewer x:Name="ContentPanel" Grid.Row="2" Margin="12,0,12,0">
            <StackPanel>

                <TextBlock Text="{Binding Path=Details, Mode=OneWay}"  Margin="12,0,0,0"
                 TextWrapping="Wrap" />
                
                <TextBlock Text="{Binding Path=StartTime, Mode=OneWay}"  Margin="12,12,0,0"/>
                <TextBlock Text="{Binding Path=EndTime, Mode=OneWay}"  Margin="12,0,0,0"/>

                <TextBlock Text="{Binding Path=Location, Mode=OneWay}"  Margin="12,12,0,0"/>

                <TextBlock Text="{Binding Path=Status, Mode=OneWay}"  Margin="12,12,0,0"/>

                <TextBlock Text="Органайзер" Margin="12,12,0,0" />
                <ListBox ItemsSource="{Binding Path=Organizer}" ItemTemplate="{StaticResource AttendeeTemplate}"
                 Margin="24,0,0,0" />

                <TextBlock Text="Участники" Margin="12,12,0,0" />
                <ListBox ItemsSource="{Binding Path=Attendees}" ItemTemplate="{StaticResource AttendeeTemplate}"
                 Margin="24,0,0,0" />

                <TextBlock Text="Учетные записи" Margin="12,12,0,0" />
                <ListBox ItemsSource="{Binding Path=Accounts}" Margin="24,0,0,0">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>
                                <TextBlock Grid.Column="0" Text="{Binding Path=Kind, Mode=OneWay}" />
                                <TextBlock Grid.Column="1" Text=":  " />
                                <TextBlock Grid.Column="2" Text="{Binding Path=Name, Mode=OneWay}" />
                            </Grid>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </StackPanel>
        </ScrollViewer>
    </Grid>
</phone:PhoneApplicationPage>
    

Содержимое файла AppointmentDetails.xaml.cs:

using Microsoft.Phone.Controls;

namespace ContactsAndCalendarTestApp
{
    public partial class AppointmentDetails : PhoneApplicationPage
    {
        public AppointmentDetails()
        {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            //Set the data context for this page to the selected appointment
            this.DataContext = App.appt;
        }
    }
}
    

Содержимое файла ContactDetails.xaml:

<phone:PhoneApplicationPage 
    x:Class="ContactsAndCalendarTestApp.ContactDetails"
    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"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
    shell:SystemTray.IsVisible="True">

    <!--LayoutRoot is the root grid where all 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,0">
            <TextBlock x:Name="ApplicationTitle" Text="Контакты и календарь" 
              Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="Контакты" Margin="9,-7,0,0" 
              Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <!--ContentPanel - place additional content here-->
        <StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

            <TextBlock Text="{Binding Path=DisplayName, Mode=OneWay}" Foreground="{StaticResource PhoneAccentBrush}" 
            FontSize="{StaticResource PhoneFontSizeExtraLarge}" />

            <Border BorderThickness="2" HorizontalAlignment="Left"
             BorderBrush="{StaticResource PhoneAccentBrush}" >
                <Image Name="Picture" Height="85" Width="85" HorizontalAlignment="Left" />
            </Border>

            <TextBlock Text="Телефонные номера" Margin="12,12,0,0"/>
            <ListBox ItemsSource="{Binding Path=PhoneNumbers}" Height="60"  Margin="36,0,0,0">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Grid.Column="0" Text="{Binding Path=Kind, Mode=OneWay}" />
                            <TextBlock Grid.Column="1" Text=":  " />
                            <TextBlock Grid.Column="2" Text="{Binding Path=PhoneNumber, Mode=OneWay}" />
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

            <TextBlock Text="Адреса электронной почты" Margin="12,12,0,0" />
            <ListBox ItemsSource="{Binding Path=EmailAddresses}" Height="60"  Margin="36,0,0,0">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Grid.Column="0" Text="{Binding Path=Kind, Mode=OneWay}" />
                            <TextBlock Grid.Column="1" Text=":  " />
                            <TextBlock Grid.Column="2" Text="{Binding Path=EmailAddress, Mode=OneWay}" />
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

            <TextBlock Text="web-сайты" Margin="12,12,0,0" />
            <ListBox ItemsSource="{Binding Path=Websites}" Height="60"  Margin="36,0,0,0" />

            <TextBlock Text="Информация о компании" Margin="12,12,0,0" />
            <ListBox ItemsSource="{Binding Path=Companies}" Height="60"  Margin="36,0,0,0">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Grid.Column="0" Text="{Binding Path=CompanyName, Mode=OneWay}" />
                            <TextBlock Grid.Column="1" Text=":  " />
                            <TextBlock Grid.Column="2" Text="{Binding Path=JobTitle, Mode=OneWay}" />
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

            <TextBlock Text="Учетные записи" Margin="12,12,0,0" />
            <ListBox ItemsSource="{Binding Path=Accounts}" Height="60" Margin="36,0,0,0">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Grid.Column="0" Text="{Binding Path=Kind, Mode=OneWay}" />
                            <TextBlock Grid.Column="1" Text=":  " />
                            <TextBlock Grid.Column="2" Text="{Binding Path=Name, Mode=OneWay}" />
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </StackPanel>
    </Grid>
</phone:PhoneApplicationPage>
    

Содержимое файла ContactDetails.xaml.cs:

using System;
using Microsoft.Phone.Controls;
using System.Windows.Media.Imaging;

namespace ContactsAndCalendarTestApp
{
    public partial class ContactDetails : PhoneApplicationPage
    {
        public ContactDetails()
        {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            //Set the data context for this page to the selected contact
            this.DataContext = App.con;

            try
            {
                //Try to get a picture of the contact
                BitmapImage img = new BitmapImage();
                img.SetSource(App.con.GetPicture());
                Picture.Source = img;
            }
            catch (Exception)
            {
                //can't get a picture of the contact
            }
        }
    }
}
    
Страницы:

Дополнительные материалы к занятию можно скачать здесь.

Вложенные папки: ContactsAndCalendarTestApp

Ссылки: http://msdn.microsoft.com/en-us/library/hh202972(v=vs.92).aspx

В Windows Phone SDK 7.1 Beta 2 появилась возможность доступа к календарю и контактам пользователя. С помощью календаря можно получать уведомления о заранее запланированных событиях. Из контактов пользователя можно извлекать самую разную информацию, например, электронную почту, телефон, день рождения, фотографию пользователя и так далее. Теперь можно создавать приложения, извлекающие данные из самых разных источников данных. Предположим, часть данных о своих контактах пользователь хранит в самом телефоне, другая часть данных может храниться в сервисах Facebook, Windows Live, Twitter и тому подобное (таблице 34.1). Благодаря технологиям, заложенным в Windows Phone SDK 7.1 Beta 2, можно извлекать данные из подобных источников, руководствуясь разными критериями отбора.

Провайдеры данных, из которых можно извлекать информацию в Windows Phone 7.1
Провайдер данных Имя контакта Изображение контакта Другие данные контакта События календаря
Устройство Windows Phone Да Да Да Да
Социальная сеть Windows Live Да Да Да Да
Windows Live Rolodex Да Да Да Да
Учетные записи MS Exchange (учетные записи из локальной адресной книги, не из глобального списка адресов) Да Да Да Да
Адресная книга мобильного оператора Да Да Да Нет
Facebook Да Да Нет Нет
Агрегированные сети Windows Live (Twitter, LinkedIn и другие) Нет Нет Нет Нет

В предлагаемой работе мы рассмотрим пример, описанный на сайте Microsoft (http://msdn.microsoft.com/en-us/library/hh202972(v=vs.92).aspx) (мы русифицировали интерфейс). Приложение осуществляет поиск информации, хранящейся в контактах пользователя по имени, телефону, электронной почте (рис 34.1) или по дате (рис 34.2).

(рис 34.1) Поиск информации можно осуществлять по имени, телефону и адресу электронной почты (рис 34.2) Поиск по дате

Для начала нам нужно создать с помощью Visual Studio проект Silverlight for Windows Phone 7.1. Назовем приложение ContactsAndCalendarTestApp. Добавьте ссылки на библиотеки Microsoft.Phone.Controls.dll и mscorlib.extensions.dll.

Откройте файл MainPage.xaml и заполните его следующим содержимым:

<phone:PhoneApplicationPage 
    x:Class="ContactsAndCalendarTestApp.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:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:MyApp="clr-namespace:ContactsAndCalendarTestApp"
    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">

    <phone:PhoneApplicationPage.Resources>

        <DataTemplate x:Key="AccountTemplate">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0" Text="{Binding Path=Name, Mode=OneWay}" />
                <TextBlock Grid.Column="1" Text=" account: " />
                <TextBlock Grid.Column="2" Text="{Binding Path=Kind, Mode=OneWay}" />
            </Grid>
        </DataTemplate>

        <MyApp:ContactPictureConverter x:Key="ContactPictureConverter" />

    </phone:PhoneApplicationPage.Resources>

    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">

        <!--Pivot Control-->
        <controls:Pivot Title="Контакты и календарь" >

            <!--Pivot item one-->
            <controls:PivotItem Header="Контакты">

                <StackPanel Height="Auto" Width="Auto" HorizontalAlignment="Stretch" 
                  VerticalAlignment="Stretch" >

                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>

                        <TextBox Grid.Row="0" Grid.ColumnSpan="2" Name="contactFilterString" />
                        <RadioButton Grid.Row="1" Grid.Column="0" Checked="FilterChange"
                         Name="name" Content="Имя" />
                        <RadioButton Grid.Row="1" Grid.Column="1" Checked="FilterChange"
                         Name="phone" Content="Телефон"/>
                        <RadioButton Grid.Row="2" Grid.Column="0" Checked="FilterChange"
                         Name="email" Content="email"/>
                        <Button Grid.Row="2" Grid.Column="1" Content="Поиск"
                         Click="SearchContacts_Click" />
                    </Grid>

                    <TextBlock Name="ContactResultsLabel" Text="Поиск контактов" TextWrapping="Wrap" Margin="12,0,0,0" />

                    <ListBox Name="ContactResultsData" ItemsSource="{Binding}" Tap="ContactResultsData_Tap"
                     Height="300" Margin="24,0,0,0" >
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal" >
                                    <Border BorderThickness="2" HorizontalAlignment="Left" VerticalAlignment="Center"
                                     BorderBrush="{StaticResource PhoneAccentBrush}" >
                                        <Image Source="{Binding Converter={StaticResource ContactPictureConverter}}" Width="48"
                                         Height="48" Stretch="Fill"  />
                                    </Border>
                                    <TextBlock Name="ContactResults" Text="{Binding Path=DisplayName, Mode=OneWay}"
                                     FontSize="{StaticResource PhoneFontSizeExtraLarge}" Margin="18,8,0,0" />
                                </StackPanel>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>

                </StackPanel>
            </controls:PivotItem>


            <!--Pivot item two-->
            <controls:PivotItem Header="Учетные записи">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>

                    <StackPanel Grid.Row="0" >

                        <TextBlock Text="Учетная запись контакта" Foreground="{StaticResource PhoneAccentBrush}" 
                        Style="{StaticResource PhoneTextLargeStyle}" />
                        <ListBox Name="ContactAccounts" ItemsSource="{Binding}" ItemTemplate="{StaticResource AccountTemplate}" 
                        Height="200" Margin="24,0,0,0" />
                    </StackPanel>

                    <StackPanel Grid.Row="1" >

                        <TextBlock Text="Контакты событий" Foreground="{StaticResource PhoneAccentBrush}" 
                        Style="{StaticResource PhoneTextLargeStyle}" />
                        <ListBox Name="CalendarAccounts" ItemsSource="{Binding}" ItemTemplate="{StaticResource AccountTemplate}" 
                        Height="200" Margin="24,0,0,0" />
                    </StackPanel>
                </Grid>
            </controls:PivotItem>


            <!--Pivot item three-->
            <controls:PivotItem Header="События">
                <StackPanel Height="Auto" Width="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >

                    <TextBlock Text="События между" Foreground="{StaticResource PhoneAccentBrush}" />

                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>

                        <TextBlock Grid.Row="0" Grid.Column="0" Text="Дата начала" />
                        <TextBlock Grid.Row="0" Grid.Column="1" Text="Дата завершения" />
                        <TextBlock Grid.Row="1" Grid.Column="0" Text="placeholder" Name="StartDate" />
                        <TextBlock Grid.Row="1" Grid.Column="1" Text="placeholder" Name="EndDate" />
                        <Button Grid.Row="2" Grid.ColumnSpan="2" Content="search" 
                        Click="SearchAppointments_Click" HorizontalAlignment="Center" />
                    </Grid>

                    <TextBlock Name="AppointmentResultsLabel" Text="Поиск событий" TextWrapping="Wrap" />

                    <ListBox Name="AppointmentResultsData" ItemsSource="{Binding}" 
                    Tap="AppointmentResultsData_Tap" Height="400"  ScrollViewer.ManipulationMode="Control" Margin="24,0,0,0" >
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Path=Subject, Mode=OneWay}"
                                  FontSize="{StaticResource PhoneFontSizeExtraLarge}" />
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </StackPanel>
            </controls:PivotItem>
        </controls:Pivot>
    </Grid>
</phone:PhoneApplicationPage>
    

Далее, откройте файл кода MainPage.xaml.cs и введите следующий код:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Microsoft.Phone.Controls;
using Microsoft.Phone.UserData;

namespace ContactsAndCalendarTestApp
{
    public partial class MainPage : PhoneApplicationPage
    {
        FilterKind contactFilterKind = FilterKind.None;

        // Constructor
        public MainPage()
        {
            InitializeComponent();

            name.IsChecked = true;

            ContactAccounts.DataContext = (new Contacts()).Accounts;
            CalendarAccounts.DataContext = (new Appointments()).Accounts;
        }


        //-------------------------------------------------------------------------------
        //-- Contact Methods
        //-------------------------------------------------------------------------------
        private void SearchContacts_Click(object sender, RoutedEventArgs e)
        {
            ContactResultsLabel.Text = "Загружаю результаты ...";
            ContactResultsData.DataContext = null;

            Contacts cons = new Contacts();

            cons.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(Contacts_SearchCompleted);

            cons.SearchAsync(contactFilterString.Text, contactFilterKind, "Contacts Test #1");
        }


        void Contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
        {
            //MessageBox.Show(e.State.ToString());

            try
            {
                //Bind the results to the listbox that displays them in the UI
                ContactResultsData.DataContext = e.Results;
            }
            catch (System.Exception)
            {
                //That's okay, no results
            }

            if (ContactResultsData.Items.Count > 0)
            {
                ContactResultsLabel.Text = "Результаты (Раскройте подробности ...)";
            }
            else
            {
                ContactResultsLabel.Text = "Ничего не найдено";
            }
        }


        private void FilterChange(object sender, RoutedEventArgs e)
        {
            String option = ((RadioButton)sender).Name;

            InputScope scope = new InputScope();
            InputScopeName scopeName = new InputScopeName();

            switch (option)
            {
                case "name":
                    contactFilterKind = FilterKind.DisplayName;
                    scopeName.NameValue = InputScopeNameValue.Text;
                    break;

                case "phone":
                    contactFilterKind = FilterKind.PhoneNumber;
                    scopeName.NameValue = InputScopeNameValue.TelephoneNumber;
                    break;

                case "email":
                    contactFilterKind = FilterKind.EmailAddress;
                    scopeName.NameValue = InputScopeNameValue.EmailSmtpAddress;
                    break;

                default:
                    contactFilterKind = FilterKind.None;
                    break;
            }

            scope.Names.Add(scopeName);
            contactFilterString.InputScope = scope;
            contactFilterString.Focus();
        }


        private void ContactResultsData_Tap(object sender, GestureEventArgs e)
        {
            App.con = ((sender as ListBox).SelectedValue as Contact);

            NavigationService.Navigate(new Uri("/ContactDetails.xaml", UriKind.Relative));
        }


        //-------------------------------------------------------------------------------
        //-- Appointment Methods
        //-------------------------------------------------------------------------------
        private void SearchAppointments_Click(object sender, RoutedEventArgs e)
        {
            AppointmentResultsLabel.Text = "Загружаю результаты ...";
            AppointmentResultsData.DataContext = null;
            Appointments appts = new Appointments();

            appts.SearchCompleted += new EventHandler<AppointmentsSearchEventArgs>(Appointments_SearchCompleted);

            DateTime start = new DateTime();
            start = DateTime.Now;
            //MessageBox.Show(start.ToLongDateString());

            DateTime end = new DateTime();
            end = start.AddDays(7);
            //MessageBox.Show(end.ToLongDateString());

            appts.SearchAsync(start, end, 20, "Appointments Test #1");
        }


        void Appointments_SearchCompleted(object sender, AppointmentsSearchEventArgs e)
        {
            //MessageBox.Show(e.State.ToString());

            StartDate.Text = e.StartTimeInclusive.ToShortDateString();
            EndDate.Text = e.EndTimeInclusive.ToShortDateString();

            try
            {
                //Bind the results to the listbox that displays them in the UI
                AppointmentResultsData.DataContext = e.Results;
            }
            catch (System.Exception)
            {
                //That's okay, no results
            }

            if (AppointmentResultsData.Items.Count > 0)
            {
                AppointmentResultsLabel.Text = "Результаты (Нажмите для получения деталей...)";
            }
            else
            {
                AppointmentResultsLabel.Text = "Ничего не найдено";
            }
        }


        private void AppointmentResultsData_Tap(object sender, GestureEventArgs e)
        {
            App.appt = ((sender as ListBox).SelectedValue as Appointment);

            NavigationService.Navigate(new Uri("/AppointmentDetails.xaml", UriKind.Relative));
        }
    }//End page class


    //-------------------------------------------------------------------------------
    //-- Contact Photo Converter
    //-------------------------------------------------------------------------------
    public class ContactPictureConverter : System.Windows.Data.IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            Contact c = value as Contact;
            if (c == null) return null;

            System.IO.Stream imageStream = c.GetPicture();
            if (null != imageStream)
            {
                return Microsoft.Phone.PictureDecoder.DecodeJpeg(imageStream);
            }
            return null;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }//End converter class


}//End namespace
    

Далее, необходимо открыть файл App.xaml.cs и заполнить его следующим содержимым:

using System.Windows;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace ContactsAndCalendarTestApp
{
    public partial class App : Application
    {
        public static Microsoft.Phone.UserData.Contact con;
        public static Microsoft.Phone.UserData.Appointment appt;

        /// <summary>
        /// Provides easy access to the root frame of the Phone Application.
        /// </summary>
        /// <returns>The root frame of the Phone Application.</returns>
        public PhoneApplicationFrame RootFrame { get; private set; }

        /// <summary>
        /// Constructor for the Application object.
        /// </summary>
        public App()
        {
            // Global handler for uncaught exceptions. 
            UnhandledException += Application_UnhandledException;

            // Standard Silverlight initialization
            InitializeComponent();

            // Phone-specific initialization
            InitializePhoneApplication();

            // Show graphics profiling information while debugging.
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // Display the current frame rate counters.
                //Application.Current.Host.Settings.EnableFrameRateCounter = true;

                // Show the areas of the app that are being redrawn in each frame.
                //Application.Current.Host.Settings.EnableRedrawRegions = true;

                // Enable non-production analysis visualization mode, 
                // which shows areas of a page that are handed off to GPU with a colored overlay.
                //Application.Current.Host.Settings.EnableCacheVisualization = true;

                // Disable the application idle detection by setting the UserIdleDetectionMode property of the
                // application's PhoneApplicationService object to Disabled.
                // Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run
                // and consume battery power when the user is not using the phone.
                PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
            }

        }

        // Code to execute when the application is launching (eg, from Start)
        // This code will not execute when the application is reactivated
        private void Application_Launching(object sender, LaunchingEventArgs e)
        {
        }

        // Code to execute when the application is activated (brought to foreground)
        // This code will not execute when the application is first launched
        private void Application_Activated(object sender, ActivatedEventArgs e)
        {
        }

        // Code to execute when the application is deactivated (sent to background)
        // This code will not execute when the application is closing
        private void Application_Deactivated(object sender, DeactivatedEventArgs e)
        {
        }

        // Code to execute when the application is closing (eg, user hit Back)
        // This code will not execute when the application is deactivated
        private void Application_Closing(object sender, ClosingEventArgs e)
        {
        }

        // Code to execute if a navigation fails
        private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // A navigation has failed; break into the debugger
                System.Diagnostics.Debugger.Break();
            }
        }

        // Code to execute on Unhandled Exceptions
        private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        {
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // An unhandled exception has occurred; break into the debugger
                System.Diagnostics.Debugger.Break();
            }
        }

        #region Phone application initialization

        // Avoid double-initialization
        private bool phoneApplicationInitialized = false;

        // Do not add any additional code to this method
        private void InitializePhoneApplication()
        {
            if (phoneApplicationInitialized)
                return;

            // Create the frame but don't set it as RootVisual yet; this allows the splash
            // screen to remain active until the application is ready to render.
            RootFrame = new PhoneApplicationFrame();
            RootFrame.Navigated += CompleteInitializePhoneApplication;

            // Handle navigation failures
            RootFrame.NavigationFailed += RootFrame_NavigationFailed;

            // Ensure we don't initialize again
            phoneApplicationInitialized = true;
        }

        // Do not add any additional code to this method
        private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
        {
            // Set the root visual to allow the application to render
            if (RootVisual != RootFrame)
                RootVisual = RootFrame;

            // Remove this handler since it is no longer needed
            RootFrame.Navigated -= CompleteInitializePhoneApplication;
        }

        #endregion
    }
}
    

Для нашего приложения понадобятся также файлы AppointmentDetails.xaml (AppointmentDetails.xaml.cs) и ContactDetails.xaml (ContactDetails.xaml.cs). Их нужно создать выполнив следующую последовательность действий: Solution Explorer -> Add -> New Item -> Windows Phone Portrait Page -> AppointmentDetails.xaml (ContactDetails.xaml) и Solution Explorer -> Add -> New Item -> Code File -> AppointmentDetails.xaml.cs (ContactDetails.xaml.cs).

Первые два файла для отображения результатов поиска по дате, вторые два - по контактной информации.

Итак, содержимое файла AppointmentDetails.xaml:

<phone:PhoneApplicationPage 
    x:Class="ContactsAndCalendarTestApp.AppointmentDetails"
    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"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
    shell:SystemTray.IsVisible="True">

    <phone:PhoneApplicationPage.Resources>

        <DataTemplate x:Key="AttendeeTemplate">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0" Text="{Binding Path=DisplayName,
                 Mode=OneWay}" TextWrapping="Wrap" />
                <TextBlock Grid.Column="1" Text=":  " />
                <TextBlock Grid.Column="2" Text="{Binding Path=EmailAddress,
                 Mode=OneWay}" TextWrapping="Wrap" />
            </Grid>
        </DataTemplate>
    </phone:PhoneApplicationPage.Resources>


    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <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,6">
            <TextBlock x:Name="ApplicationTitle" Text="Контакты и календарь"
             Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="Подробности" Margin="9,-7,0,0"
             Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <TextBlock Grid.Row="1" Text="{Binding Path=Subject, Mode=OneWay}"
         Foreground="{StaticResource PhoneAccentBrush}" FontSize="{StaticResource PhoneFontSizeExtraLarge}"
          TextWrapping="Wrap" />

        <!--ContentPanel - place additional content here-->
        <ScrollViewer x:Name="ContentPanel" Grid.Row="2" Margin="12,0,12,0">
            <StackPanel>

                <TextBlock Text="{Binding Path=Details, Mode=OneWay}"  Margin="12,0,0,0"
                 TextWrapping="Wrap" />
                
                <TextBlock Text="{Binding Path=StartTime, Mode=OneWay}"  Margin="12,12,0,0"/>
                <TextBlock Text="{Binding Path=EndTime, Mode=OneWay}"  Margin="12,0,0,0"/>

                <TextBlock Text="{Binding Path=Location, Mode=OneWay}"  Margin="12,12,0,0"/>

                <TextBlock Text="{Binding Path=Status, Mode=OneWay}"  Margin="12,12,0,0"/>

                <TextBlock Text="Органайзер" Margin="12,12,0,0" />
                <ListBox ItemsSource="{Binding Path=Organizer}" ItemTemplate="{StaticResource AttendeeTemplate}"
                 Margin="24,0,0,0" />

                <TextBlock Text="Участники" Margin="12,12,0,0" />
                <ListBox ItemsSource="{Binding Path=Attendees}" ItemTemplate="{StaticResource AttendeeTemplate}"
                 Margin="24,0,0,0" />

                <TextBlock Text="Учетные записи" Margin="12,12,0,0" />
                <ListBox ItemsSource="{Binding Path=Accounts}" Margin="24,0,0,0">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>
                                <TextBlock Grid.Column="0" Text="{Binding Path=Kind, Mode=OneWay}" />
                                <TextBlock Grid.Column="1" Text=":  " />
                                <TextBlock Grid.Column="2" Text="{Binding Path=Name, Mode=OneWay}" />
                            </Grid>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </StackPanel>
        </ScrollViewer>
    </Grid>
</phone:PhoneApplicationPage>
    

Содержимое файла AppointmentDetails.xaml.cs:

using Microsoft.Phone.Controls;

namespace ContactsAndCalendarTestApp
{
    public partial class AppointmentDetails : PhoneApplicationPage
    {
        public AppointmentDetails()
        {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            //Set the data context for this page to the selected appointment
            this.DataContext = App.appt;
        }
    }
}
    

Содержимое файла ContactDetails.xaml:

<phone:PhoneApplicationPage 
    x:Class="ContactsAndCalendarTestApp.ContactDetails"
    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"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
    shell:SystemTray.IsVisible="True">

    <!--LayoutRoot is the root grid where all 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,0">
            <TextBlock x:Name="ApplicationTitle" Text="Контакты и календарь" 
              Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="Контакты" Margin="9,-7,0,0" 
              Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <!--ContentPanel - place additional content here-->
        <StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

            <TextBlock Text="{Binding Path=DisplayName, Mode=OneWay}" Foreground="{StaticResource PhoneAccentBrush}" 
            FontSize="{StaticResource PhoneFontSizeExtraLarge}" />

            <Border BorderThickness="2" HorizontalAlignment="Left"
             BorderBrush="{StaticResource PhoneAccentBrush}" >
                <Image Name="Picture" Height="85" Width="85" HorizontalAlignment="Left" />
            </Border>

            <TextBlock Text="Телефонные номера" Margin="12,12,0,0"/>
            <ListBox ItemsSource="{Binding Path=PhoneNumbers}" Height="60"  Margin="36,0,0,0">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Grid.Column="0" Text="{Binding Path=Kind, Mode=OneWay}" />
                            <TextBlock Grid.Column="1" Text=":  " />
                            <TextBlock Grid.Column="2" Text="{Binding Path=PhoneNumber, Mode=OneWay}" />
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

            <TextBlock Text="Адреса электронной почты" Margin="12,12,0,0" />
            <ListBox ItemsSource="{Binding Path=EmailAddresses}" Height="60"  Margin="36,0,0,0">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Grid.Column="0" Text="{Binding Path=Kind, Mode=OneWay}" />
                            <TextBlock Grid.Column="1" Text=":  " />
                            <TextBlock Grid.Column="2" Text="{Binding Path=EmailAddress, Mode=OneWay}" />
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

            <TextBlock Text="web-сайты" Margin="12,12,0,0" />
            <ListBox ItemsSource="{Binding Path=Websites}" Height="60"  Margin="36,0,0,0" />

            <TextBlock Text="Информация о компании" Margin="12,12,0,0" />
            <ListBox ItemsSource="{Binding Path=Companies}" Height="60"  Margin="36,0,0,0">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Grid.Column="0" Text="{Binding Path=CompanyName, Mode=OneWay}" />
                            <TextBlock Grid.Column="1" Text=":  " />
                            <TextBlock Grid.Column="2" Text="{Binding Path=JobTitle, Mode=OneWay}" />
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

            <TextBlock Text="Учетные записи" Margin="12,12,0,0" />
            <ListBox ItemsSource="{Binding Path=Accounts}" Height="60" Margin="36,0,0,0">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Grid.Column="0" Text="{Binding Path=Kind, Mode=OneWay}" />
                            <TextBlock Grid.Column="1" Text=":  " />
                            <TextBlock Grid.Column="2" Text="{Binding Path=Name, Mode=OneWay}" />
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </StackPanel>
    </Grid>
</phone:PhoneApplicationPage>
    

Содержимое файла ContactDetails.xaml.cs:

using System;
using Microsoft.Phone.Controls;
using System.Windows.Media.Imaging;

namespace ContactsAndCalendarTestApp
{
    public partial class ContactDetails : PhoneApplicationPage
    {
        public ContactDetails()
        {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            //Set the data context for this page to the selected contact
            this.DataContext = App.con;

            try
            {
                //Try to get a picture of the contact
                BitmapImage img = new BitmapImage();
                img.SetSource(App.con.GetPicture());
                Picture.Source = img;
            }
            catch (Exception)
            {
                //can't get a picture of the contact
            }
        }
    }
}
    
Вернуться к учебному плану