- •Основы разработки приложений беспроводных устройств
- •Среда разработки
- •Шаблоны приложений
- •Создание простого приложения
- •Добавление элементов управления на страницу xaml
- •Добавление новых страниц в проект
- •Навигация между страницами приложения
- •Лабораторный практикум 1: версия для печати и pda Лабораторная работа №1. Телефонная книжка
- •Лабораторная работа №2. Блокнот
- •Лабораторная работа №3. Меню ресторана
- •Лабораторная работа №4. Калькулятор
- •Лабораторная работа №5. База паролей
- •Лабораторная работа №6. Учет затрат
- •Лабораторная работа №7. Список задач
- •Лабораторная работа №8. Веб-браузер
- •Лабораторная работа №9. Игра "Загони шар в лузу"
- •Лабораторная работа №10. Определение местоположения
Лабораторная работа №3. Меню ресторана
Задание
Создать приложение "Меню ресторана" для Windows Phone 7 с использованием компонента Panorama. Предусмотреть возможность ввода номера дисконтной карты и подсчета скидки в реальном времени.
Освоение
основные элементы управления и разметки (Grid, StackPanel, TextBox, TextBlock, CheckBox, Button)
компонент Panorama
события
контекст ввода
Описание
Создадим новый проект Silverlight for Windows Phone – Windows Phone Application.
Приложение будет состоять из одного окна, основанного на компоненте Panorama. Данный компонент позволяет выводить информацию за границы экрана, оставаясь в рамках одного окна. При перемещении между областями видимости происходит смещение картинки на заднем фоне. Потому компонент и получил название Panorama.
Откроем файл разметки главной страницы MainPage.xaml. Компонент Panorama имеет свой заголовок, поэтому с целью экономии места на экране закомментируем или удалим часть кода, отвечающего за заголовок окна TitlePanel:
<!--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="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel-->
Наше приложение будет автоматически подсчитывать сумму счета и вычислять скидку в случае, если введен код дисконтной карты. Таким образом, на экране необходимо разместить элементы вывода такой информации. Представим разметки страницы в виде таблицы с одним столбцом и двумя строками. В первой строке будет расположен компонент Panorama, во второй – элементы вывода суммы счета.
Для того чтобы создать компонент Panorama на странице, необходимо добавить в References нашего проекта компонент Microsoft.Phone.Controls и в файле xaml в самый верх добавить пространство имен:
xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"
Примечание: Вместо "controls" можно придумать любое другое название. В этом случае на странице разметки при использовании элементов управления из данного пространства имен нужно использовать соответствующее указанное название.
Добавим в элемент Grid с именем ContentPanel разметку страницы. Внутри элемента Grid вначале нужно объявить, сколько будет строк и сколько столбцов у нашей таблицы. Каждому элементу содержимого страницы присваиваются индексы строк и столбцов Grid.Column и Grid.Row.
Компоненту controls:Panorama зададим атрибут заголовка (Title). Внутри определим фоновую картинку с помощью тега controls:Panorama.Background (картинку с указанным названием необходимо добавить в проект приложения):
<controls:Panorama.Background>
<ImageBrush ImageSource="Panorama.jpg" />
</controls:Panorama.Background>
Содержимое панорамы будем помещать в элементы controls:PanoramaItem. Каждому элементу зададим заголовок (Header), соответствующий "странице" меню ресторана: салаты, первое, второе, напитки и скидка.
После компонента controls:Panorama определим элементы TextBlock, объединенные в блок StackPanel.
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="90" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<controls:Panorama Title="кафешка" Grid.Column="0" Grid.Row="0">
<controls:Panorama.Background>
<ImageBrush ImageSource="Panorama.jpg" />
</controls:Panorama.Background>
<controls:PanoramaItem Header="салаты">
</controls:PanoramaItem>
<controls:PanoramaItem Header="первое">
</controls:PanoramaItem>
<controls:PanoramaItem Header="второе">
</controls:PanoramaItem>
<controls:PanoramaItem Header="напитки">
</controls:PanoramaItem>
<controls:PanoramaItem Header="скидка">
</controls:PanoramaItem>
</controls:Panorama>
<!-- Посчет суммы в реальном времени -->
<StackPanel Grid.Column="0" Grid.Row="1">
<TextBlock Name="lblSum" Text="Сумма: 0 р." VerticalAlignment="Bottom" Margin="12,0,12,0" />
<TextBlock Name="lblDsc" Text="Скидки нет" VerticalAlignment="Bottom" Margin="12,0,12,0" />
<TextBlock Name="lblAll" Text="Итого: 0 р." VerticalAlignment="Bottom" Margin="12,0,12,0" />
</StackPanel>
</Grid>
Создадим раздел меню "салаты". Для этого в первый элемент PanoramaItem добавим таблицу Grid, состоящую из 4 колонок. В первой будет располагаться CheckBox с наименованием салата (при нажатии на него будем изменять сумму счета). Во второй – TextBlock с массой салата в граммах. В третьей – TextBlock с ценой салата. В четвертой – валюта ("р."). Такое разделение задумано специально, чтобы автоматизировать процесс подсчета стоимости заказа. Для этого мы просто буем суммировать значения 3 колонки для всех включенных элементов CheckBox. Можно реализовать и другую логику, в том числе можно сделать меню динамическим списком.
<controls:PanoramaItem Header="салаты">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="70" />
<RowDefinition Height="70" />
<RowDefinition Height="70" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="230" />
<ColumnDefinition Width="70" />
<ColumnDefinition Width="60" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<CheckBox Name="checkSalad1" Content="Греческий" FontSize="26" VerticalAlignment="Center"
Grid.Column="0" Grid.Row="0" Click="checkSalad1_Click" />
<TextBlock Text="100 г" FontSize="22" HorizontalAlignment="Right"
VerticalAlignment="Center" Grid.Column="1" Grid.Row="0" />
<TextBlock Name="costSalad1" Text="70" FontSize="22" HorizontalAlignment="Right"
VerticalAlignment="Center" Grid.Column="2" Grid.Row="0" />
<TextBlock Text=" р." FontSize="22" HorizontalAlignment="Left"
VerticalAlignment="Center" Grid.Column="3" Grid.Row="0" />
<CheckBox Name="checkSalad2" Content="Крабовый" FontSize="26" VerticalAlignment="Center"
Grid.Column="0" Grid.Row="1" Click="checkSalad2_Click" />
<TextBlock Text="100 г" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center"
Grid.Column="1" Grid.Row="1" />
<TextBlock Name="costSalad2" Text="40" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center"
Grid.Column="2" Grid.Row="1" />
<TextBlock Text=" р." FontSize="22" HorizontalAlignment="Left" VerticalAlignment="Center"
Grid.Column="3" Grid.Row="1" />
<CheckBox Name="checkSalad3" Content="Оливье" FontSize="26" VerticalAlignment="Center"
Grid.Column="0" Grid.Row="2" Click="checkSalad3_Click" />
<TextBlock Text="100 г" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center"
Grid.Column="1" Grid.Row="2" />
<TextBlock Name="costSalad3" Text="45" FontSize="22" HorizontalAlignment="Right"
VerticalAlignment="Center" Grid.Column="2" Grid.Row="2" />
<TextBlock Text=" р." FontSize="22" HorizontalAlignment="Left" VerticalAlignment="Center"
Grid.Column="3" Grid.Row="2" />
</Grid>
</controls:PanoramaItem>
Аналогичным образом реализуем разделы меню "первое", "второе" и "напитки":
<controls:PanoramaItem Header="первое">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="70" />
<RowDefinition Height="70" />
<RowDefinition Height="70" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="230" />
<ColumnDefinition Width="70" />
<ColumnDefinition Width="60" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<CheckBox Name="checkSup1" Content="Борщ" FontSize="26" VerticalAlignment="Center" Grid.Column="0"
Grid.Row="0" Click="checkSup1_Click" />
<TextBlock Text="200 г" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center" Grid.Column="1"
Grid.Row="0" />
<TextBlock Name="costSup1" Text="50" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center"
Grid.Column="2" Grid.Row="0" />
<TextBlock Text=" р." FontSize="22" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Column="3"
Grid.Row="0" />
<CheckBox Name="checkSup2" Content="Грибной" FontSize="26" VerticalAlignment="Center" Grid.Column="0"
Grid.Row="1" Click="checkSup2_Click" />
<TextBlock Text="200 г" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center" Grid.Column="1"
Grid.Row="1" />
<TextBlock Name="costSup2" Text="60" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center"
Grid.Column="2" Grid.Row="1" />
<TextBlock Text=" р." FontSize="22" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Column="3"
Grid.Row="1" />
<CheckBox Name="checkSup3" Content="Солянка" FontSize="26" VerticalAlignment="Center" Grid.Column="0"
Grid.Row="2" Click="checkSup3_Click" />
<TextBlock Text="200 г" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center" Grid.Column="1"
Grid.Row="2" />
<TextBlock Name="costSup3" Text="55" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center"
Grid.Column="2" Grid.Row="2" />
<TextBlock Text=" р." FontSize="22" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Column="3"
Grid.Row="2" />
</Grid>
</controls:PanoramaItem>
<controls:PanoramaItem Header="второе">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="70" />
<RowDefinition Height="70" />
<RowDefinition Height="70" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="230" />
<ColumnDefinition Width="70" />
<ColumnDefinition Width="60" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<CheckBox Name="checkSec1" Content="Котлеты" FontSize="26" VerticalAlignment="Center"
Grid.Column="0" Grid.Row="0" Click="checkSec1_Click" />
<TextBlock Text="200 г" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center"
Grid.Column="1" Grid.Row="0" />
<TextBlock Name="costSec1" Text="60" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center"
Grid.Column="2" Grid.Row="0" />
<TextBlock Text=" р." FontSize="22" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Column="3"
Grid.Row="0" />
<CheckBox Name="checkSec2" Content="Отбивная" FontSize="26" VerticalAlignment="Center" Grid.Column="0"
Grid.Row="1" Click="checkSec2_Click" />
<TextBlock Text="200 г" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center" Grid.Column="1"
Grid.Row="1" />
<TextBlock Name="costSec2" Text="100" FontSize="22" HorizontalAlignment="Right"
VerticalAlignment="Center" Grid.Column="2" Grid.Row="1" />
<TextBlock Text=" р." FontSize="22" HorizontalAlignment="Left" VerticalAlignment="Center"
Grid.Column="3" Grid.Row="1" />
<CheckBox Name="checkSec3" Content="Плов" FontSize="26" VerticalAlignment="Center"
Grid.Column="0"
Grid.Row="2" Click="checkSec3_Click" />
<TextBlock Text="200 г" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center" Grid.Column="1"
Grid.Row="2" />
<TextBlock Name="costSec3" Text="80" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center"
Grid.Column="2" Grid.Row="2" />
<TextBlock Text=" р." FontSize="22" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Column="3"
Grid.Row="2" /> </Grid>
</controls:PanoramaItem>
<controls:PanoramaItem Header="напитки">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="70" />
<RowDefinition Height="70" />
<RowDefinition Height="70" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="230" />
<ColumnDefinition Width="70" />
<ColumnDefinition Width="60" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<CheckBox Name="checkDrnk1" Content="Компот" FontSize="26" VerticalAlignment="Center"
Grid.Column="0" Grid.Row="0" Click="checkDrnk1_Click" />
<TextBlock Text="0,2 л" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center"
Grid.Column="1" Grid.Row="0" />
<TextBlock Name="costDrnk1" Text="15" FontSize="22" HorizontalAlignment="Right"
VerticalAlignment="Center" Grid.Column="2" Grid.Row="0" />
<TextBlock Text=" р." FontSize="22" HorizontalAlignment="Left" VerticalAlignment="Center"
Grid.Column="3" Grid.Row="0" />
<CheckBox Name="checkDrnk2" Content="Сок" FontSize="26" VerticalAlignment="Center"
Grid.Column="0" Grid.Row="1" Click="checkDrnk2_Click" />
<TextBlock Text="0,2 л" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center"
Grid.Column="1" Grid.Row="1" />
<TextBlock Name="costDrnk2" Text="20" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center"
Grid.Column="2" Grid.Row="1" />
<TextBlock Text=" р." FontSize="22" HorizontalAlignment="Left" VerticalAlignment="Center"
Grid.Column="3" Grid.Row="1" />
<CheckBox Name="checkDrnk3" Content="Чай" FontSize="26" VerticalAlignment="Center"
Grid.Column="0" Grid.Row="2" Click="checkDrnk3_Click" />
<TextBlock Text="0,2 л" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center"
Grid.Column="1" Grid.Row="2" />
<TextBlock Name="costDrnk3" Text="15" FontSize="22" HorizontalAlignment="Right" VerticalAlignment="Center"
Grid.Column="2" Grid.Row="2" />
<TextBlock Text=" р." FontSize="22" HorizontalAlignment="Left" VerticalAlignment="Center"
Grid.Column="3" Grid.Row="2" />
</Grid>
</controls:PanoramaItem>
В раздел ввода скидки добавим элемент TextBlock, текстовое поле для ввода номера дисконтной карты и две кнопки: "Применить скидку" и "Сбросить". Поскольку в текстовое поле требуется вводить только цифры, определим контекст ввода. Для этого атрибуту InputScope элемента TextBox присвоим значение Number. Таким образом, при нажатии на TextBox клавиатура телефона будет принимать следующий вид:
Рис. 2.4. Клавиатура для ввода номера карты
<controls:PanoramaItem Header="скидка">
<StackPanel>
<TextBlock Text="Введите номер карты:" FontSize="26" />
<TextBox Name="txtDiscount" Text="" InputScope="Number" />
<Button Name="btnDiscount" Content="Применить скидку" Click="btnDiscount_Click" />
<Button Name="btnDiscNull" Content="Сбросить" Click="btnDiscNull_Click" />
</StackPanel>
</controls:PanoramaItem>
Перейдем к написанию логики приложения. Откроем файл MainPage.xaml.cs.
В класс MainPage добавим константу, определяющую размер возможной скидки, и две переменные: одна для хранения суммы счета, другая для определения, активирован ли код скидки.
private const float DISCOUNT = 0.10f; //размер скидки
private float m_nSumma;
private bool m_IsDiscount;
Для хранения списка существующих скидочных кодов создадим еще одну переменную – список значений типа int. И для сопровождения списка создадим функцию проверки правильности кода:
private List<int> Codes;
private bool IsCodeAgree(int code)
{
bool bRes = false;
for (int i = 0; i < Codes.Count; i++)
{
if (Codes[i] == code)
{
bRes = true;
break;
}
}
return bRes;
}
В конструкторе класса MainPage будем инициализировать эти переменные. Также создадим несколько скидочный кодов по-умолчанию:
// Constructor
public MainPage()
{
InitializeComponent();
Codes = new List<int>();
Codes.Add(1111111111);
Codes.Add(1234567890);
Codes.Add(0101010101);
m_nSumma = 0;
m_IsDiscount = false;
}
В обработчиках нажатия на CheckBox будем менять сумму счета и обновлять ее в поле TextBlock. Также в функции RefreshSum() будем вычислять скидку и выводить итоговое значение счета внизу главной страницы приложения:
private void RefreshSum()
{
lblSum.Text = "Сумма: " + m_nSumma.ToString() + " р.";
if (m_IsDiscount)
{
lblDsc.Text = "Скидка " + (m_nSumma * DISCOUNT).ToString() + " р. (" + ((int)(DISCOUNT * 100)).ToString() + "%)";
lblAll.Text = "Итого: " + (m_nSumma * (1f - DISCOUNT)).ToString() + " р.";
}
else
{
lblDsc.Text = "Скидки нет";
lblAll.Text = "Итого: " + m_nSumma.ToString() + " р.";
}
}
private void checkSalad1_Click(object sender, RoutedEventArgs e)
{
int cost = int.Parse(costSalad1.Text);
m_nSumma += checkSalad1.IsChecked.Value ? cost : -cost;
RefreshSum();
}
private void checkSalad2_Click(object sender, RoutedEventArgs e)
{
int cost = int.Parse(costSalad2.Text);
m_nSumma += checkSalad2.IsChecked.Value ? cost : -cost;
RefreshSum();
}
private void checkSalad3_Click(object sender, RoutedEventArgs e)
{
int cost = int.Parse(costSalad3.Text);
m_nSumma += checkSalad3.IsChecked.Value ? cost : -cost;
RefreshSum();
}
private void checkSup1_Click(object sender, RoutedEventArgs e)
{
int cost = int.Parse(costSup1.Text);
m_nSumma += checkSup1.IsChecked.Value ? cost : -cost;
RefreshSum();
}
private void checkSup2_Click(object sender, RoutedEventArgs e)
{
int cost = int.Parse(costSup2.Text);
m_nSumma += checkSup2.IsChecked.Value ? cost : -cost;
RefreshSum();
}
private void checkSup3_Click(object sender, RoutedEventArgs e)
{
int cost = int.Parse(costSup3.Text);
m_nSumma += checkSup3.IsChecked.Value ? cost : -cost;
RefreshSum();
}
private void checkSec1_Click(object sender, RoutedEventArgs e)
{
int cost = int.Parse(costSec1.Text);
m_nSumma += checkSec1.IsChecked.Value ? cost : -cost;
RefreshSum();
}
private void checkSec2_Click(object sender, RoutedEventArgs e)
{
int cost = int.Parse(costSec2.Text);
m_nSumma += checkSec2.IsChecked.Value ? cost : -cost;
RefreshSum();
}
private void checkSec3_Click(object sender, RoutedEventArgs e)
{
int cost = int.Parse(costSec3.Text);
m_nSumma += checkSec3.IsChecked.Value ? cost : -cost;
RefreshSum();
}
private void checkDrnk1_Click(object sender, RoutedEventArgs e)
{
int cost = int.Parse(costDrnk1.Text);
m_nSumma += checkDrnk1.IsChecked.Value ? cost : -cost;
RefreshSum();
}
private void checkDrnk2_Click(object sender, RoutedEventArgs e)
{
int cost = int.Parse(costDrnk2.Text);
m_nSumma += checkDrnk2.IsChecked.Value ? cost : -cost;
RefreshSum();
}
private void checkDrnk3_Click(object sender, RoutedEventArgs e)
{
int cost = int.Parse(costDrnk3.Text);
m_nSumma += checkDrnk3.IsChecked.Value ? cost : -cost;
RefreshSum();
}
При нажатии на кнопку "Применить скидку" будем проверять код дисконтной карты, а при нажатии на кнопку "Сбросить" выключать подсчет скидки:
private void btnDiscount_Click(object sender, RoutedEventArgs e)
{
int code = 0;
if (int.TryParse(txtDiscount.Text, out code))
{
if (IsCodeAgree(code))
{
m_IsDiscount = true;
RefreshSum();
}
else
{
MessageBox.Show("Неверный код.");
}
}
else
{
MessageBox.Show("Неверный код.");
}
}
private void btnDiscNull_Click(object sender, RoutedEventArgs e)
{
txtDiscount.Text = "";
m_IsDiscount = false;
RefreshSum();
}
Теперь можно скомпилировать приложение, запустить на эмуляторе или телефоне и проверить его функциональность.
