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

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

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

Лабораторная работа №2. Блокнот

Задание

Создать приложение "Блокнот" для Windows Phone 7 с возможностью изменения настроек текста (шрифт, размер, цвет, выравнивание).

Освоение

  • навигация между страницами
  • основные элементы управления и разметки (Grid, StackPanel, TextBox, TextBlock, Button, RadioButton, CheckBox, Slider, ScrollViewer)
  • события
  • компонент Pivot
  • меню приложения

Описание

Создадим новый проект Silverlight for Windows PhoneWindows Phone Application. Приложение будет состоять из 2 окон:

  • основное с текстовым полем
  • окно настроек

Начнем с основного окна.

Откроем файл разметки главной страницы MainPage.xaml. Изменим текст названия приложения ApplicationTitle, например, на "БЛОКНОТ". Для того чтобы выделить больше места для текстового поля, закомментируем или удалим блок заголовка страницы PageTitle.

<!--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>

Внутрь объекта Grid с именем ContentPanel поместим элемент ScrollViewer, а внутрь него TextBox. ScrollViewer нужен для обеспечения вертикальной прокрутки текстового поля. Определим ширину, высоту и автоматическое появление ScrollViewer. Текстовому полю дадим имя txtMain, назначим размер шрифта по умолчанию 24. Также выставим свойства AcceptsReturn="True" (перенос строки при нажатии на кнопку Enter на клавиатуре) и TextWrapping="Wrap" (перенос текста на новую строку по достижении границы текстового поля).

< !--ContentPanel - place additional content here-->
        < Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            < ScrollViewer Height="620" Width="450" VerticalScrollBarVisibility="Auto">
                < TextBox Name="txtMain" Text="Здесь можно печатать любой текст"
                 FontSize="24" AcceptsReturn="True" TextWrapping="Wrap" />
            < /ScrollViewer>
        < /Grid>

Создадим меню на главной странице нашего приложения. Для этого в самом низу файла MainPage.xaml уберем комментарии, в которые заключен тег phone:PhoneApplicationPage.ApplicationBar и его содержимое. Удалим элементы shell:ApplicationBarIconButton и оставим только один элемент shell:ApplicationBarMenuItem. Назначим ему текст "Настройки" и событие Click="MenuProperties_Click".

<!--Sample code showing usage of ApplicationBar-->
    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
            <shell:ApplicationBar.MenuItems>
                <shell:ApplicationBarMenuItem Text="Настройки" Click="MenuProperties_Click" />
            </shell:ApplicationBar.MenuItems>
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>

Перейдем к написанию кода страницы. Для этого откроем файл MainPage.xaml.cs.

Для обеспечения перехода между страницами добавим в самый верх директиву:

using System.Windows.Navigation;

Теперь обдумаем, каким образом буем осуществлять передачу настроек текстового поля между страницами. Поскольку нам пока неизвестно, как работать файлами и локальной базой в Windows Phone 7, создадим статический класс Properties со статическими переменными:

public static class Properties
    {
        public static bool bApply;

        public static int nFontSize;
        public static string strFontFamily;
        public static bool bItalic;
        public static bool bBold;

        public static TextAlignment taHAlignment;

        public static Color colorFont;
        public static Color colorBack;
    }

Теперь в обработчике нажатия на кнопку меню напишем сохранение параметров текстового поля. После этого будем осуществлять переход на страницу настроек:

private void MenuProperties_Click(object sender, EventArgs e)
        {
            Properties.nFontSize = (int)txtMain.FontSize;
            Properties.strFontFamily = txtMain.FontFamily.Source;

            Properties.bItalic = (txtMain.FontStyle == FontStyles.Italic);
            Properties.bBold = (txtMain.FontWeight == FontWeights.Bold);

            Properties.taHAlignment = txtMain.TextAlignment;

            Properties.colorFont = ((SolidColorBrush)txtMain.Foreground).Color;
            Properties.colorBack = ((SolidColorBrush)txtMain.Background).Color;

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

Добавим в проект новую страницу – Windows Phone Portrait Page. Назовем ее PropertiesPage. Откроем файл PropertiesPage.xaml и приступим к написанию разметки окна настроек.

Так как настроек достаточно много, все они на одной странице будут выглядеть громоздко. Поэтому можно использовать компонент Pivot, который является аналогом панели вкладок в Windows-приложениях для настольного ПК Рис. 2.3 .

Пример панели вкладок в Windows-приложениях

Рис. 2.3. Пример панели вкладок в Windows-приложениях

Для того чтобы создать компонент Pivot на странице, необходимо добавить в References нашего проекта компонент Microsoft.Phone.Controls и в файле xaml в самый верх добавить пространство имен:

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

Примечание: Вместо "controls" можно придумать любое другое название. В этом случае на странице разметки при использовании элементов управления из данного пространства имен нужно использовать соответствующее указанное название.

Теперь мы можем создать компонент Pivot:

< controls:Pivot Title="НАСТРОЙКИ">
                
            < controls:PivotItem Header="шрифт">
            < /controls:PivotItem>
                
            < controls:PivotItem Header="текст">
            < /controls:PivotItem>
                
            < controls:PivotItem Header="цвет">
            < /controls:PivotItem>
        < /controls:Pivot>

Поместим внутрь каждого "таба" элементы для изменения параметров текстового поля. Назовем первый – "шрифт". Будем менять шрифт, размер и начертание текста в текстовом поле. Для изменения размера будем использовать элементы Slider и TextBlock. Для изменения шрифта – несколько RadioButton. Для изменения начертания – CheckBox. Все элементы поместим внутрь таблицы Grid, состоящей из 2 колонок и 3 строк:

<controls:PivotItem Header="шрифт">
                <Grid Margin="10,0,10,0">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="90"/>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>

                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="180" />
                        <ColumnDefinition Width="270" />
                    </Grid.ColumnDefinitions>

                    <TextBlock Text="Шрифт: " Margin="0,15,0,0" FontSize="26" Grid.Column="0" Grid.Row="0" />
                    <StackPanel Orientation="Horizontal"  Grid.Column="1" Grid.Row="0">
                        <Slider Name="sliderFontSize" Value="24" Minimum="1" Maximum="72"
                         Width="200" ValueChanged="sliderFontSize_ValueChanged" SmallChange="1" />
                        <TextBlock Name="lblFontSize" Text="24" FontSize="26" VerticalAlignment="Center" />
                    </StackPanel>

                    <TextBlock Text="Размер: " VerticalAlignment="Top" FontSize="26" Margin="0,15,0,0" 
                    Grid.Column="0" Grid.Row="1" />
                    <StackPanel Grid.Column="1" Grid.Row="1">
                        <RadioButton GroupName="fontSize" Name="radioFont1" Content="Segoe WP" 
                        IsChecked="True" Click="radioFont1_Click" />
                        <RadioButton GroupName="fontSize" Name="radioFont2" Content="Verdana"
                        FontFamily="Verdana" Click="radioFont2_Click" />
                        <RadioButton GroupName="fontSize" Name="radioFont3" Content="Courier New"
                         FontFamily="Courier New" Click="radioFont3_Click" />
                    </StackPanel>

                    <TextBlock Text="Начертания: " VerticalAlignment="Top" FontSize="26" 
                    Margin="0,15,0,0" Grid.Column="0" Grid.Row="2" />
                    <StackPanel Grid.Column="1" Grid.Row="2">
                        <CheckBox Name="checkItalic" Content="Курсив" Grid.Column="1" 
                        Grid.Row="2" FontStyle="Italic" Click="checkItalic_Click" />
                        <CheckBox Name="checkBold" Content="Полужирный" Grid.Column="1" 
                        Grid.Row="3" FontWeight="Bold" Click="checkBold_Click" />
                    </StackPanel>
                </Grid>
            </controls:PivotItem>

Второй PivotItem назовем "текст". Сюда добавим только RadioButton, с помощью которых будем задавать выравнивание:

<controls:PivotItem Header="текст">
                <Grid Margin="10,0,10,0">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="224" />
                    </Grid.RowDefinitions>

                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="200" />
                        <ColumnDefinition Width="270" />
                    </Grid.ColumnDefinitions>

                    <TextBlock Text="Выравнивание по горизонтали: " FontSize="26" Margin="0,15,0,0" 
                    TextWrapping="Wrap" Grid.Column="0" Grid.Row="0" />
                    <StackPanel Grid.Column="1" Grid.Row="0">
                        <RadioButton GroupName="hAlign" Name="radioHAl1" Content="Center" 
                        Click="radioHAl1_Click" />
                        <RadioButton GroupName="hAlign" Name="radioHAl2" Content="Left" I
                        sChecked="True" Click="radioHAl2_Click" />
                        <RadioButton GroupName="hAlign" Name="radioHAl3" Content="Right"
                         Click="radioHAl3_Click" />
                    </StackPanel>
                </Grid>
            </controls:PivotItem>

Третий PivotItem назовем "цвет". Здесь будем менять цвета шрифта и фона текстового поля. Для этого воспользуемся элементом управления Rectangle. Также в этот элемент добавим небольшое текстовое поле, на котором будем демонстрировать пользователю сочетание выбранных им цветов:

<controls:PivotItem Header="цвет">
                <Grid Margin="10,0,10,0">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="200" />
                        <RowDefinition Height="200" />
                        <RowDefinition />
                    </Grid.RowDefinitions>

                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="200" />
                        <ColumnDefinition Width="270" />
                    </Grid.ColumnDefinitions>

                    <TextBlock Text="Цвет шрифта: " FontSize="26" Margin="0,15,0,0" 
TextWrapping="Wrap" Grid.Column="0" Grid.Row="0" />
                    <StackPanel Grid.Column="1" Grid.Row="0">
                        <Rectangle Height="32" Name="rectFont1" Stroke="White" StrokeThickness="1" 
                        Fill="Black" MouseEnter="rectFont1_MouseEnter" />
                        <Rectangle Height="32" Name="rectFont2" Stroke="Black" StrokeThickness="1" 
                        Fill="Red" MouseEnter="rectFont2_MouseEnter" />
                        <Rectangle Height="32" Name="rectFont3" Stroke="Black" StrokeThickness="1" 
                        Fill="Green" MouseEnter="rectFont3_MouseEnter" />
                        <Rectangle Height="32" Name="rectFont4" Stroke="Black" StrokeThickness="1" 
                        Fill="Blue" MouseEnter="rectFont4_MouseEnter" />
                        <Rectangle Height="32" Name="rectFont5" Stroke="Black" StrokeThickness="1" 
                        Fill="Yellow" MouseEnter="rectFont5_MouseEnter" />
                        <Rectangle Height="32" Name="rectFont6" Stroke="Black" StrokeThickness="1" 
                        Fill="White" MouseEnter="rectFont6_MouseEnter" />
                    </StackPanel>

                    <TextBlock Text="Цвет фона: " FontSize="26" Margin="0,15,0,0" 
TextWrapping="Wrap" Grid.Column="0" Grid.Row="1" />
                    <StackPanel Grid.Column="1" Grid.Row="1">
                        <Rectangle Height="32" Name="rectBack1" Stroke="White" StrokeThickness="1"
                         Fill="Black" MouseEnter="rectBack1_MouseEnter" />
                        <Rectangle Height="32" Name="rectBack2" Stroke="Black" StrokeThickness="1" 
                        Fill="Red" MouseEnter="rectBack2_MouseEnter" />
                        <Rectangle Height="32" Name="rectBack3" Stroke="Black" StrokeThickness="1" 
                        Fill="Green" MouseEnter="rectBack3_MouseEnter" />
                        <Rectangle Height="32" Name="rectBack4" Stroke="Black" StrokeThickness="1" 
                        Fill="Blue" MouseEnter="rectBack4_MouseEnter" />
                        <Rectangle Height="32" Name="rectBack5" Stroke="Black" StrokeThickness="1" 
                        Fill="Yellow" MouseEnter="rectBack5_MouseEnter" />
                        <Rectangle Height="32" Name="rectBack6" Stroke="Black" StrokeThickness="1"
                         Fill="White" MouseEnter="rectBack6_MouseEnter" />
                    </StackPanel>

                    <TextBox Name="txtSample" Text="Пример" Height="80" Width="200" Grid.Row="2" Grid.ColumnSpan="2" />
                </Grid>
            </controls:PivotItem>
        </controls:Pivot>

По аналогии со страницей MainPage.xaml раскомментируем внизу элементы меню. Оставим две кнопки "Принять" и "Отмена":

<!--Sample code showing usage of ApplicationBar--<
    <phone:PhoneApplicationPage.ApplicationBar<
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"<
            <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" 
            Text="Принять" Click="btnApply_Click" /<
            <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" 
            Text="Отмена" Click="btnCancel_Click" /<
            <!--shell:ApplicationBar.MenuItems<
                <shell:ApplicationBarMenuItem x:Name="menuItem1" Text="MenuItem 1"/<
                <shell:ApplicationBarMenuItem x:Name="menuItem2" Text="MenuItem 2"/<
            </shell:ApplicationBar.MenuItems--<
        </shell:ApplicationBar<
    </phone:PhoneApplicationPage.ApplicationBar<

Перейдем к коду.

При нажатии на элементы раздела "шрифт" будем записывать в переменные глобального класса соответствующие новые значения. Поскольку значения элемента Slider могут быть нецелыми, будем их округлять. Новое значение будем писать в TextBlock с именем lblFontSize для удобства пользователя:

private void sliderFontSize_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (null != sliderFontSize)
            {
                Properties.nFontSize = (int)Math.Round(sliderFontSize.Value);
                lblFontSize.Text = Properties.nFontSize.ToString();
            }
        }

        private void radioFont1_Click(object sender, RoutedEventArgs e)
        {
            Properties.strFontFamily = radioFont1.Content.ToString();
        }

        private void radioFont2_Click(object sender, RoutedEventArgs e)
        {
            Properties.strFontFamily = radioFont2.Content.ToString();
        }

        private void radioFont3_Click(object sender, RoutedEventArgs e)
        {
            Properties.strFontFamily = radioFont3.Content.ToString();
        }

        private void checkItalic_Click(object sender, RoutedEventArgs e)
        {
            Properties.bItalic = checkItalic.IsChecked.Value;
        }

        private void checkBold_Click(object sender, RoutedEventArgs e)
        {
            Properties.bBold = checkBold.IsChecked.Value;
        }

Аналогичные обработчики событий сделаем для элементов вкладки "текст":

private void radioHAl1_Click(object sender, RoutedEventArgs e)
        {
            Properties.taHAlignment = TextAlignment.Center;
        }

        private void radioHAl2_Click(object sender, RoutedEventArgs e)
        {
            Properties.taHAlignment = TextAlignment.Left;
        }

        private void radioHAl3_Click(object sender, RoutedEventArgs e)
        {
            Properties.taHAlignment = TextAlignment.Right;
        }

        private void radioHAl4_Click(object sender, RoutedEventArgs e)
        {
            Properties.taHAlignment = TextAlignment.Justify;
        }

При обработке нажатий на элементы Rectangle будем записывать цвет в переменную и присваивать небольшому текстовому полю на странице:

private void rectFont1_MouseEnter(object sender, MouseEventArgs e)
        {
            txtSample.Foreground = rectFont1.Fill;
            Properties.colorFont = Color.FromArgb(255, 0, 0, 0);
        }

        private void rectFont2_MouseEnter(object sender, MouseEventArgs e)
        {
            txtSample.Foreground = rectFont2.Fill;
            Properties.colorFont = Color.FromArgb(255, 255, 0, 0);
        }

        private void rectFont3_MouseEnter(object sender, MouseEventArgs e)
        {
            txtSample.Foreground = rectFont3.Fill;
            Properties.colorFont = Color.FromArgb(255, 0, 255, 0);
        }

        private void rectFont4_MouseEnter(object sender, MouseEventArgs e)
        {
            txtSample.Foreground = rectFont4.Fill;
            Properties.colorFont = Color.FromArgb(255, 0, 0, 255);
        }

        private void rectFont5_MouseEnter(object sender, MouseEventArgs e)
        {
            txtSample.Foreground = rectFont5.Fill;
            Properties.colorFont = Color.FromArgb(255, 255, 255, 0);
        }

        private void rectFont6_MouseEnter(object sender, MouseEventArgs e)
        {
            txtSample.Foreground = rectFont6.Fill;
            Properties.colorFont = Color.FromArgb(255, 255, 255, 255);
        }

        private void rectBack1_MouseEnter(object sender, MouseEventArgs e)
        {
            txtSample.Background = new SolidColorBrush(Color.FromArgb(255, 128, 128, 128));
            Properties.colorBack = Color.FromArgb(255, 0, 0, 0);
        }

        private void rectBack2_MouseEnter(object sender, MouseEventArgs e)
        {
            txtSample.Background = rectBack2.Fill;
            Properties.colorBack = Color.FromArgb(255, 255, 0, 0);
        }

        private void rectBack3_MouseEnter(object sender, MouseEventArgs e)
        {
            txtSample.Background = rectBack3.Fill;
            Properties.colorBack = Color.FromArgb(255, 0, 255, 0);
        }

        private void rectBack4_MouseEnter(object sender, MouseEventArgs e)
        {
            txtSample.Background = rectBack4.Fill;
            Properties.colorBack = Color.FromArgb(255, 0, 0, 255);
        }

        private void rectBack5_MouseEnter(object sender, MouseEventArgs e)
        {
            txtSample.Background = rectBack5.Fill;
            Properties.colorBack = Color.FromArgb(255, 255, 255, 0);
        }

        private void rectBack6_MouseEnter(object sender, MouseEventArgs e)
        {
            txtSample.Background = rectBack6.Fill;
            Properties.colorBack = Color.FromArgb(255, 255, 255, 255);
        }

Для обеспечения перехода на главную страницу пропишем наверху директиву:

using System.Windows.Navigation;

Теперь напишем обработчики нажатия на кнопки меню. Так как при прямом переходе на главную страницу, она будет перезагружена, и данные потеряны, переход будем выполнять с помощью команды NavigationService.GoBack(). Данные будут передавать посредством статического класса Properties.

private void btnApply_Click(object sender, EventArgs e)
        {
            Properties.bApply = true;

            //если перейти на страницу /MainPage.xaml, она будет обновлена, а данные потеряны
            //поэтому ГоБэк
            NavigationService.GoBack();
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            MessageBoxResult result = MessageBox.Show("Изменения будут потеряны. Продолжить?", 
"Отмена", MessageBoxButton.OKCancel);
            if (result == MessageBoxResult.OK)
            {
                Properties.bApply = false;

                NavigationService.GoBack();
            }
        }

Переменная Properties.bApply нужна для того, чтобы на главной странице при присвоении текстовому полю новых параметров, знать, проинициализированы ли соответствующие переменные класса Properties.

Теперь напишем обработчик инициализации элементов управления при переходе на страницу настроек. Для этого перегрузим метод OnNavigatedTo() и внутри него будем задавать для каждого элемента управления значение соответствующей переменной класса Properties:

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

            sliderFontSize.Value = Properties.nFontSize;

            if (Properties.strFontFamily.Equals("Verdana"))
            {
                radioFont2.IsChecked = true;
            }
            else
            {
                if (Properties.strFontFamily.Equals("Courier New"))
                {
                    radioFont3.IsChecked = true;
                }
                else
                {
                    radioFont1.IsChecked = true; //Segoe WP
                }
            }

            checkItalic.IsChecked = Properties.bItalic;
            checkBold.IsChecked = Properties.bBold;

            if (TextAlignment.Center == Properties.taHAlignment)
            {
                radioHAl1.IsChecked = true;
            }
            else
            {
                if (TextAlignment.Right == Properties.taHAlignment)
                {
                    radioHAl3.IsChecked = true;
                }
                else
                {
                    radioHAl2.IsChecked = true; //Left
                }
            }

            txtSample.Foreground = new SolidColorBrush(Properties.colorFont);
            txtSample.Background = new SolidColorBrush(Properties.colorBack);
        }

Вернемся к коду главной страницы (MainPage.xaml.cs). В конструкторе выполним инициализацию статической переменной Properties.bApply:

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

            //чтобы в самом начале не выполнялся OnNavigatedTo()
            Properties.bApply = false;
        }

Перегрузим метод OnNavigatedTo(), в котором будем присваивать свойствам текстового поля значения из переменных класса Properties:

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

            if (true == Properties.bApply)
            {
                txtMain.FontSize = Properties.nFontSize;
                txtMain.FontFamily = new FontFamily(Properties.strFontFamily);

                txtMain.FontStyle = Properties.bItalic ? FontStyles.Italic : FontStyles.Normal;
                txtMain.FontWeight = Properties.bBold ? FontWeights.Bold : FontWeights.Normal;

                txtMain.TextAlignment = Properties.taHAlignment;

                txtMain.Foreground = new SolidColorBrush(Properties.colorFont);
                txtMain.Background = new SolidColorBrush(Properties.colorBack);
            }
        }

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

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