- •Основы разработки приложений беспроводных устройств
- •Среда разработки
- •Шаблоны приложений
- •Создание простого приложения
- •Добавление элементов управления на страницу xaml
- •Добавление новых страниц в проект
- •Навигация между страницами приложения
- •Лабораторный практикум 1: версия для печати и pda Лабораторная работа №1. Телефонная книжка
- •Лабораторная работа №2. Блокнот
- •Лабораторная работа №3. Меню ресторана
- •Лабораторная работа №4. Калькулятор
- •Лабораторная работа №5. База паролей
- •Лабораторная работа №6. Учет затрат
- •Лабораторная работа №7. Список задач
- •Лабораторная работа №8. Веб-браузер
- •Лабораторная работа №9. Игра "Загони шар в лузу"
- •Лабораторная работа №10. Определение местоположения
Лабораторная работа №8. Веб-браузер
Задание
Создать простой веб-браузер для Windows Phone 7 с адресной строкой, историей посещений и сохранением истории в изолированном хранилище.
Освоение
элемент управления WebBrowser
изолированное хранилище
Описание
Создадим новый проект Silverlight for Windows Phone – Windows Phone Application.
Откроем файл разметки главной страницы MainPage.xaml. Добавим текстовое поле (для адресной строки), кнопку (при нажатии на нее будет происходить переход) и элементWebBrowser. Обратите внимание, что браузер находится в пространстве имен "phone", т.о. не требуется подключение дополнительных библиотек. В меню добавим 3 кнопки для навигации по истории (вперед, назад и просмотр). При нажатии на кнопку просмотра истории будем переходить на другую страницу, где в списке будем выводить посещенные страницы.
Полностью разметка главной страницы примет следующий вид:
<phone:PhoneApplicationPage
x:Class="Wp7IUSLab11.HistoryPage"
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="696" 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,28">
<TextBlock x:Name="ApplicationTitle" Text="ОБОЗРЕВАТЕЛЬ (история)"
Style="{StaticResource PhoneTextNormalStyle}"/>
<!--TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0"
Style="{StaticResource PhoneTextTitle1Style}"/-->
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox Name="lstHistory">
</ListBox>
</Grid>
</Grid>
<!--Sample code showing usage of ApplicationBar-->
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
<shell:ApplicationBarIconButton IconUri="/Images/appbar.back.rest.png"
Text="назад" Click="Menu1_Click" />
<shell:ApplicationBarIconButton IconUri="/Images/appbar.cancel.rest.png"
Text="очистить" Click="Menu2_Click" />
<shell:ApplicationBarIconButton IconUri="/Images/appbar.next.rest.png"
Text="перейти" Click="Menu3_Click" />
<!--shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem Text="MenuItem 1"/>
<shell:ApplicationBarMenuItem Text="MenuItem 2"/>
</shell:ApplicationBar.MenuItems-->
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
</phone:PhoneApplicationPage>
Разметка второй страницы будет состоять только из пустого списка (мы будем заполнять его динамически в коде страницы). Меню будет состоять из 3 кнопок (назад, перейти по выделенной ссылке и очистить историю).
<phone:PhoneApplicationPage
x:Class="Wp7IUSLab11.HistoryPage"
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="696" 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,28">
<TextBlock x:Name="ApplicationTitle" Text="ОБОЗРЕВАТЕЛЬ (история)"
Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0"
Style="{StaticResource PhoneTextTitle1Style}"/-->
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox Name="lstHistory" />
</Grid>
</Grid>
<!--Sample code showing usage of ApplicationBar-->
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
<shell:ApplicationBarIconButton IconUri="/Images/appbar.back.rest.png"
Text="назад" Click="Menu1_Click" />
<shell:ApplicationBarIconButton IconUri="/Images/appbar.cancel.rest.png"
Text="очистить" Click="Menu2_Click" />
<shell:ApplicationBarIconButton IconUri="/Images/appbar.next.rest.png"
Text="перейти" Click="Menu3_Click" />
<!--shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem Text="MenuItem 1"/>
<shell:ApplicationBarMenuItem Text="MenuItem 2"/>
</shell:ApplicationBar.MenuItems-->
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
</phone:PhoneApplicationPage>
Для того чтобы упростить взаимодействие между страницами приложения создадим статический класс History, который будет содержать статический список ссылок, индекс текущего элемента списка и несколько функций:
public static class History
{
public static List<Uri> listHistory;
public static int nCurHistoryPos;
public static void Init()
{
listHistory = new List<Uri>();
nCurHistoryPos = 0;
}
public static string ListToString()
{
string strRes = "";
for (int i = 0; i < listHistory.Count; i++)
{
if (i != 0)
{
strRes += "|";
}
strRes += listHistory[i].ToString();
}
return strRes;
}
public static void StringToList(string strHist)
{
string[] strMas = strHist.Split( '|');
for (int i = 0; i < strMas.GetLength(0); i++)
{
listHistory.Add(new Uri(strMas[i]));
}
}
}
Вернемся к файлу MainPage.xaml.cs. При нажатии на кнопку btnRun будем осуществлять загрузку в браузере страницы, адрес которой указан в текстовом поле. При этом в случае если ссылка не содержит "http://", то его обязательно будем добавлять:
private void btnRun_Click(object sender, RoutedEventArgs e)
{
try
{
//убираем пробелы и приводим к нижнему регистру
txtAddress.Text = txtAddress.Text.Trim().ToLower();
//добавляем, если надо, "http://"
if (txtAddress.Text.Length < 7)
{
txtAddress.Text = "http://" + txtAddress.Text;
}
else
{
if (!txtAddress.Text.Substring(0, 7).Equals("http://"))
{
txtAddress.Text = "http://" + txtAddress.Text;
}
}
//переходим
Uri url = new Uri(txtAddress.Text);
wBrowser.Navigate(url);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Как только страница в браузере загружена, будем добавлять ее в историю. При этом, если история полна, будем удалять последний элемент:
private void wBrowser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
//если мы движемся не по истории
if (!bHistoryNavigate)
{
if (History.listHistory.Count > 0)
{
//в случае, если бродили по истории - подтираем ее до текущей позиции
History.listHistory.RemoveRange(0, History.nCurHistoryPos);
if (!History.listHistory[0].Equals(wBrowser.Source))
{
AddToHistoryUri();
}
}
else
{
AddToHistoryUri();
}
}
else
{
//устанавливаем флаг назад в фолс
bHistoryNavigate = false;
}
txtAddress.Text = wBrowser.Source.AbsoluteUri;
}
При добавлении ссылки в историю будем сохранять всю историю в изолированном хранилище:
private void AddToHistoryUri()
{
if (History.listHistory.Count >= MAX_HISTORY_LEN)
{
History.listHistory.RemoveAt(History.listHistory.Count - 1);
}
History.listHistory.Insert(0, wBrowser.Source);
string strHistoryText = History.ListToString();
SaveToIsolatedStorage(strHistoryText);
}
Создадим константу для хранения имени файла, в который будем сохранять историю:
private const string strIStorageName = "Wp7IUSLab11.txt";
В конструкторе класса будем загружать историю из изолированного хранилища - файла (в случае, если файл существует):
// Constructor
public MainPage()
{
InitializeComponent();
History.Init();
if (IsIsolatedStorageExist())
{
string strText = LoadFromIsolatedStorage();
History.StringToList(strText);
if (History.listHistory.Count > 0)
{
txtAddress.Text = "идет загрузка...";
wBrowser.Navigate(History.listHistory[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);
}
}
Для работы с изолированным хранилищем в код необходимо добавить директивы:
using System.IO.IsolatedStorage;
using System.IO;
При переходе на главную страницу будем загружать указанную страницу. В случае если история пуста, будем очищать изолированное хранилище:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (NavigationContext.QueryString.ContainsKey("hist"))
{
History.nCurHistoryPos = int.Parse(NavigationContext.QueryString["hist"].ToString());
bHistoryNavigate = true;
wBrowser.Navigate(History.listHistory[History.nCurHistoryPos]);
}
else
{
if (0 == History.listHistory.Count)
{
RemoveIsolatedStorage();
}
}
}
Теперь можно скомпилировать приложение, запустить на эмуляторе или телефоне и проверить его функциональность.
