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

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

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

Лабораторная работа №3. Меню ресторана

Задание

Создать приложение "Меню ресторана" для Windows Phone 7 с использованием компонента Panorama. Предусмотреть возможность ввода номера дисконтной карты и подсчета скидки в реальном времени.

Освоение

  • основные элементы управления и разметки (Grid, StackPanel, TextBox, TextBlock, CheckBox, Button)
  • компонент Panorama
  • события
  • контекст ввода

Описание

Создадим новый проект Silverlight for Windows PhoneWindows 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 :

Клавиатура для ввода номера карты

Рис. 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();
        }

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

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