Опубликован: 11.01.2013 | Доступ: свободный | Студентов: 623 / 123 | Длительность: 12:06:00
Лекция 3:

Лабораторный практикум 2

< Лекция 2 || Лекция 3: 12345 || Лекция 4 >

Лабораторная работа №10. Определение местоположения

Задание

Создать приложение для Windows Phone 7 с использованием карты, определения местоположения и возможностью сохранения и демонстрации сохраненных мест на карте.

Освоение

  • карта и определение местоположения
  • изолированное хранилище

Описание

Создадим новый проект Silverlight for Windows PhoneWindows Phone Application.

Откроем файл разметки главной страницы MainPage.xaml . Для использования карт (элемента управления Map) необходимо подключить библиотеку Microsoft.Phone.Controls.Maps и добавить в файл разметки пространство имен:

xmlns:my="clr-namespace:Microsoft.Phone.Controls.Maps;assembly=Microsoft.Phone.Controls.Maps"

Наше приложение будем основано на элементах Pivot. Для этого подключим библиотеку Microsoft.Phone.Controls и добавим пространство имен:

xmlns:ctrl="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"   

В первый PivotItem поместим карту и элементы для сохранения названия места. Во второй PivotItemсписок сохраненных мест и 2 кнопки для удаления и отображения выбранного места.

      <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <ctrl:Pivot Name="myPivot" SelectionChanged="myPivot_SelectionChanged">
                <ctrl:PivotItem Header="карта">
                    <Canvas>
                        <my:Map Name="myMap" Height="529" Width="450" />

                        <Border Name="msgPlaceName" Visibility="Collapsed" BorderThickness="4" BorderBrush="White" 
 Canvas.Left="0" Canvas.Top="75" Canvas.ZIndex="2">
                            <StackPanel Width="430" Background="Black">
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock Text="Введите название места:" FontSize="26" 
Width="350" Margin="10,10,10,10" />
                                    <TextBlock Text="X" TextAlignment="Right" FontSize="26" 
Width="30" Margin="10,10,10,10" MouseEnter="lblPlaceNameX_MouseEnter" />
                                </StackPanel>
                                <TextBox Name="txtPlaceName" />
                                <Button Name="btnPlaceNameApply" Content="Принять" 
Margin="0,0,5,0" Click="btnPlaceNameApply_Click" />
                            </StackPanel>
                        </Border>
                    </Canvas>
                </ctrl:PivotItem>
                
                <ctrl:PivotItem Name="piPlaces" Header="мои места">
                    <StackPanel>
                        <ListBox Name="lstPlaces" Height="550" />

                        <StackPanel Orientation="Horizontal">
                            <Button Name="btnPlacesShow" Content="Показать"
                              Width="220" 
                            Click="btnPlacesShow_Click" />
                            <Button Name="btnPlacesDelete" Content="Удалить" 
                                Width="220" 
                            Click="btnPlacesDelete_Click"  />
                        </StackPanel>
                    </StackPanel>
                </ctrl:PivotItem>
            </ctrl:Pivot>
        </Grid>
 

Добавим также меню с 3 кнопками (увеличить масштаб, уменьшить, показать текущее местоположение) и еще 2 контекстными элементами (переключение режима и сохранение местоположения):

        <!--Sample code showing usage of ApplicationBar-->
    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
            <shell:ApplicationBarIconButton IconUri="/Images/appbar.minus.rest.png" 
            Text="Масштаб -" Click="MenuZoomSub_Click" />
            <shell:ApplicationBarIconButton IconUri="/Images/appbar.add.rest.png" 
            Text="Масштаб +" Click="MenuZoomAdd_Click" />
            <shell:ApplicationBarIconButton IconUri="/Images/appbar.feature.search.rest.png" 
            Text="Где я?" Click="MenuCurrentPos_Click" />
            
            <shell:ApplicationBar.MenuItems>>
                <shell:ApplicationBarMenuItem Text="режим" Click="MenuMapMode_Click" />
                <shell:ApplicationBarMenuItem Text="сохранить" Click="MenuSavePos_Click" />
            </shell:ApplicationBar.MenuItems>
        </shell:ApplicationBar>

    </phone:PhoneApplicationPage.ApplicationBar>

Перейдем к написанию кода.

Для начала опишем структуру для сохранения мест. Она будет содержать имя места и координаты:

struct Coords
 {
   public string Name;         //название места
   public double Latitude;     //широта
   public double Longitude;    //долгота
 }

В классе определим глобальную переменную – список:

private List<Coords> Places; 

Для работы с определением местоположения и отметками на карте необходимо прописать следующие директивы:

using Microsoft.Phone.Controls.Maps;
using System.Device.Location;

Определим две глобальные переменные:

private GeoCoordinateWatcher m_GeoWatcher;
private Pushpin myPushpin;

Немного изменим конструктор класса (проинициализируем некоторые переменные) и добавим обработчик события изменения местоположения:

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

    myMap.ZoomLevel = 1.0d;

    Places = new List<Coords>();

    m_GeoWatcher = new GeoCoordinateWatcher();
    m_GeoWatcher.MovementThreshold = 100.0f;
    m_GeoWatcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<
    GeoCoordinate>>(m_GeoWatcher_PositionChanged);

    myPushpin = new Pushpin();
    new Thread(startMyGeoWatcher).Start();
}

private void m_GeoWatcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
    myPushpin.Location = e.Position.Location;
}

void startMyGeoWatcher()
{
    m_GeoWatcher.TryStart(false, TimeSpan.FromSeconds(60));
}

При нажатии на кнопку меню "Где я?" будем добавлять Pushpin с текущими координатами на карту:

     private void ShowPosition(GeoCoordinate coords)
{
    myMap.Center = coords;
    myMap.Children.Clear();

    if (!myMap.Children.Contains(myPushpin))
    {
Pushpin pshpn = new Pushpin();
pshpn.Location = coords;

myMap.Children.Add(pshpn);
    }
}
 

При нажатии на кнопки изменения масштаба будем изменять свойство ZoomLevel карты на 1. При нажатии на кнопку смены режима будем менять свойство Mode. При сохранении текущего положения будем отображать элементы, объединенные элементом msgPlaceName .

    private void MenuZoomAdd_Click(object sender, EventArgs e)
        {
            myMap.ZoomLevel += 1;
        }

        private void MenuZoomSub_Click(object sender, EventArgs e)
        {
            myMap.ZoomLevel -= 1;
        }

        private void MenuCurrentPos_Click(object sender, EventArgs e)
        {
            ShowPosition(myPushpin.Location);
        }

        private void MenuMapMode_Click(object sender, EventArgs e)
        {
            if (myMap.Mode is RoadMode)
            {
                myMap.Mode = new AerialMode(true);
            }
            else
            {
                myMap.Mode = new RoadMode();
            }
        }

        private void MenuSavePos_Click(object sender, EventArgs e)
        {
            if (0 == myMap.Children.Count)
            {
                MessageBox.Show("Неверное действие.");
            }
            else
            {
                msgPlaceName.Visibility = System.Windows.Visibility.Visible;
                txtPlaceName.Text = "";
                myMap.IsEnabled = false;
                ApplicationBar.IsVisible = false;
                piPlaces.IsEnabled = false;
            }
        }

При выборе элемента из списка сохраненных мест, будем отображать координаты на карте:

    private void btnPlacesShow_Click(object sender, RoutedEventArgs e)
        {
            if (-1 != lstPlaces.SelectedIndex)
            {
                GeoCoordinate coords = new GeoCoordinate(Places[lstPlaces.SelectedIndex].Latitude,
                            Places[lstPlaces.SelectedIndex].Longitude);
                ShowPosition(coords);

                myPivot.SelectedIndex = 0;
                myPivot.UpdateLayout();
            }
            else
            {
                MessageBox.Show("Элемент не выбран.");
            }
        }

Сохранять список мест будем в файле в изолированном хранилище:

    private const string strIStorageName = "Wp7IUSLab13.txt";

В конструкторе в случае, если файл существует, будем загружать список из изолированного хранилища:

    if (IsIsolatedStorageExist())
        {
            FromStringToList(LoadFromIsolatedStorage());
        }

Сохранять список в изолированное хранилище лучше всего при сохранении нового места. А удалять файл при удалении, если число сохраненных мест равно 0.

Работу с изолированным хранилищем обеспечивают следующие четыре функции:

   private void SaveToIsolatedStorage(string histText)
        {
            IsolatedStorageFile fileStorage = IsolatedStorageFile.GetUserStoreForApplication();
            IsolatedStorageFileStream fileStream = fileStorage.CreateFile(strIStorageName);

            StreamWriter sw = new StreamWriter(fileStream);
            sw.Write(histText);
            sw.Close();

            fileStream.Close();
        }

        private string LoadFromIsolatedStorage()
        {
            IsolatedStorageFile fileStorage = IsolatedStorageFile.GetUserStoreForApplication();
            IsolatedStorageFileStream fileStream = fileStorage.OpenFile(strIStorageName, System.IO.FileMode.Open);

            StreamReader sr = new StreamReader(fileStream);
            string strRes = sr.ReadToEnd();
            sr.Close();
            fileStream.Close();

            return strRes;
        }

        private bool IsIsolatedStorageExist()
        {
            IsolatedStorageFile sileStorage = IsolatedStorageFile.GetUserStoreForApplication();
            return sileStorage.FileExists(strIStorageName);
        }

        private void RemoveIsolatedStorage()
        {
            if (IsIsolatedStorageExist())
            {
                IsolatedStorageFile fileStorage = IsolatedStorageFile.GetUserStoreForApplication();
                fileStorage.DeleteFile(strIStorageName);
            }
        }

Теперь можно скомпилировать приложение, запустить на эмуляторе или телефоне и проверить его функциональность.

Для тестирования приложения на эмуляторе можно использовать эмулятор определения местоположения Рис. 3.2 :

Эмулятор определения местоположения

Рис. 3.2. Эмулятор определения местоположения

< Лекция 2 || Лекция 3: 12345 || Лекция 4 >