Windows Phone 8: Создаем приложение. Матрица. Часть 2

от автора

Windows Phone 8: Создаем приложение. Матрица. Часть 1
Windows Phone 8: Создаем приложение. Матрица. Часть 2

Здравствуйте. Сегодня мы продолжим создание приложения, используем новый шаблон «Панорама», а так же добавим всевозможные настройки, что позволит изменять все параметры матрицы. Сразу оговорюсь, что при задании сильно больших чисел в некоторых настройках, резко понижается производительность, но с этим мы еще будем бороться в следующих частях.

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

Скриншот работы приложения

Хотелось вторую часть написать полностью отточенную, в плане кода, однако размеры ее стали достаточно большими. Если сразу провести еще и оптимизацию, то это усложнит прослеживание логики. Оптимизация будет в следующей части. Начнем.

Цели этой части

  1. Использовать шаблон Панорама
  2. Создание настроек приложения

Добавлены следующие настройки

  • Скорость смены символов в заданном диапазоне
  • Количество змеек в очереди
  • Количество одновременно ползущих змеек за нажатие
  • Размер шрифта
  • Старт / Стоп
  • Очистка экрана
  • Размер(количество) клеточек в матрице
  • Длина змейки в заданном диапазоне
  • Горизонтальная / Вертикальная ориентация
  • Выбор языка падающих символов
  • Цвет фона матрицы
  • Цвет первого символа
  • Градиент для змейки

Можно посмотреть эти настройки на видео:


Перейдем к работе в Visual Studio

Создаем новый проект. Приложение Windows Phone с панорамой.
У меня имя будет SE_Matrix_2d_v_4.
Остальное как в прошлый раз.

MainPage.xaml

Тут у нас добавилось немного кода. В шаблоне Панорама у меня 3 секции:

<!--Элемент управления Panorama-->         <phone:Panorama Title="">             <phone:Panorama.Background>                 <ImageBrush />             </phone:Panorama.Background>              <!--Первый элемент Panorama-->             <phone:PanoramaItem > ...             </phone:PanoramaItem>              <!--Второй элемент Panorama-->             <phone:PanoramaItem>    ...             </phone:PanoramaItem>              <!--Третий элемент Panorama-->             <phone:PanoramaItem>    ...             </phone:PanoramaItem>         </phone:Panorama> 

В первый элемент добавим непосредственно отображение матрицы. Тут ничего не поменялось, все как и в первой части:

            <!--Первый элемент Panorama-->             <phone:PanoramaItem >                 <Grid x:Name="LayoutRootSecond" Background="Black" Margin="0,-32,-2,7" RenderTransformOrigin="0.500,0.500" Tap="Event_Grid_Tap_LayoutRoot"/>             </phone:PanoramaItem> 

Во второй элемент управления добавлены первые 9 настроек из 13, описанных в начале статьи. Ничего сложного: название в TextBlock, TextBox для ввода значений и Button для применения заданного значения. Так же все обернуто в ScrollViewer для возможности вертикальной прокрутки, так как список в один экран не влезает. В большинстве TextBox метод ввода выбран как числа, InputScope=«Number». Однако в паре элементов есть возможность вводить отрицательные значения. Временно используется общая клавиатура InputScope=«Default».

Код. Второй элемент Panorama

            <!--Второй элемент Panorama-->             <phone:PanoramaItem>                     <Grid x:Name="LayoutRootThierd" Grid.Column="1" Background="Transparent" Margin="0, 0,-2,7" RenderTransformOrigin="0.500,0.500" >                     <ScrollViewer  HorizontalScrollBarVisibility="Auto"  >                         <Grid x:Name="Grid_SettingsRight" Grid.Column="1" Background="Transparent" Margin="0, 0,-2,7" RenderTransformOrigin="0.500,0.500" >                             <!-- Скорость падения змейки в мс/ Скорость смены символов в мс -->                             <TextBlock HorizontalAlignment="Left" Margin="28,3,0,0" TextWrapping="Wrap" Text="Скорость смены символов в мс" VerticalAlignment="Top" Width="352"/>                             <TextBox x:Name="TextBox_SppeedFrom" InputScope="Number" HorizontalAlignment="Left" Height="67" TextWrapping="Wrap" Text="20" VerticalAlignment="Top" Width="100" Margin="9,28,0,0"/>                             <TextBox x:Name="TextBox_SppeedTo" InputScope="Number" HorizontalAlignment="Left" Height="67" TextWrapping="Wrap" Text="40" VerticalAlignment="Top" Width="100" Margin="114,28,0,0"/>                             <Button x:Name="Button_SpeedApplay" Content=" Ok " HorizontalAlignment="Left" Height="65" Margin="288,30,0,0" VerticalAlignment="Top" Click="Event_Button_Click_SpeedApplay"/>                              <!-- Количество змеек в очереди -->                             <TextBlock HorizontalAlignment="Left" Margin="28,95,0,0" TextWrapping="Wrap" Text="Количество змеек в очереди" VerticalAlignment="Top" RenderTransformOrigin="-0.256,0.233" Width="352"/>                             <TextBox x:Name="TextBox_CountQueue" InputScope="Number" HorizontalAlignment="Left" Height="67" Margin="10,127,0,0" TextWrapping="Wrap" Text="5" VerticalAlignment="Top" Width="101" RenderTransformOrigin="0.49,-0.049"/>                             <Button x:Name="Button_CountQueue" Content=" Ok " HorizontalAlignment="Left" Margin="287,127,0,0" VerticalAlignment="Top" Click="Event_Button_Click_CountQueue" RenderTransformOrigin="1.474,0.483" Height="67"/>                              <!-- Количество змеек за нажатие -->                             <TextBlock HorizontalAlignment="Left" Margin="28,194,0,0" TextWrapping="Wrap" Text="Количество змеек за нажатие" VerticalAlignment="Top" Width="352"/>                             <TextBox x:Name="TextBox_СountSimultaneously" InputScope="Number" HorizontalAlignment="Left" Height="72" Margin="10,221,0,0" TextWrapping="Wrap" Text="1" VerticalAlignment="Top" Width="101"/>                             <Button x:Name="Button_СountSimultaneously" Content=" Ok " HorizontalAlignment="Left" Margin="288,221,0,0" VerticalAlignment="Top" Click="Event_Button_Click_СountSimultaneously" RenderTransformOrigin="1.474,0.483"/>                              <!-- Размер шрифта -->                             <TextBlock HorizontalAlignment="Left" Margin="27,293,0,0" TextWrapping="Wrap" Text="Размер шрифта (+ - [n])" VerticalAlignment="Top" Width="352"/>                             <TextBox x:Name="TextBox_FontSize" InputScope="Default" HorizontalAlignment="Left" Height="72" Margin="9,320,0,0" TextWrapping="Wrap" Text="-2" VerticalAlignment="Top" Width="101"/>                             <Button x:Name="Button_FontSize" Content=" Ok " HorizontalAlignment="Left" Margin="288,320,0,0" VerticalAlignment="Top" Click="Event_Button_Click_FontSize" RenderTransformOrigin="1.474,0.483"/>                              <!-- Количество смены символов в ячейке -->                             <TextBlock HorizontalAlignment="Left" Margin="28,392,0,0" TextWrapping="Wrap" Text="Количество смены символов" VerticalAlignment="Top" Width="352"/>                             <TextBox x:Name="TextBox_CountSymbol" InputScope="Number" HorizontalAlignment="Left" Height="72" Margin="10,419,0,0" TextWrapping="Wrap" Text="3" VerticalAlignment="Top" Width="101"/>                             <Button x:Name="Button_CountSymbol" Content=" Ok " HorizontalAlignment="Left" Margin="288,419,0,0" VerticalAlignment="Top" Click="Event_Button_Click_CountSymbol" RenderTransformOrigin="1.474,0.483"/>                              <!-- Сатрт / Стоп анимация -->                             <TextBlock x:Name="TextBlock_OnOff" HorizontalAlignment="Left" Margin="28,491,0,0" TextWrapping="Wrap" Text="Вкл/Выкл анимацию" VerticalAlignment="Top" Width="352"/>                             <ToggleButton x:Name="Button_Stop" Content="Stop" HorizontalAlignment="Left" Margin="214,523,0,0" VerticalAlignment="Top" Click="Event_Button_Click_Stop" Width="180"/>                             <ToggleButton x:Name="Button_Start" Content="Start" HorizontalAlignment="Left" Margin="10,523,0,0" VerticalAlignment="Top" Click="Event_Button_Click_Start" Width="180"/>                                                          <!-- Очистка экрана -->                             <TextBlock HorizontalAlignment="Left" Margin="28,605,0,0" TextWrapping="Wrap" Text="Хотите очистит экран?" VerticalAlignment="Top" Width="352"/>                             <Button Content=" YES " HorizontalAlignment="Left" Margin="10,632,0,0" VerticalAlignment="Top" Width="371" Click="Event_Button_Click_Clear"/>                              <!-- Размер клетки для символа -->                             <TextBlock HorizontalAlignment="Left" Margin="27,709,0,0" TextWrapping="Wrap" Text="Размер клетки для символа" VerticalAlignment="Top" Width="369"/>                             <TextBox x:Name="TextBox_ElementSize" InputScope="Default" HorizontalAlignment="Left" Height="72" Margin="10,734,0,-17" TextWrapping="Wrap" Text="-6" VerticalAlignment="Top" Width="101"/>                             <Button Content="Ok" HorizontalAlignment="Left" Margin="286,736,0,-19" VerticalAlignment="Top" Width="93" Click="Event_Button_Click_ElementSize"/>                              <!-- Длина змейки -->                             <TextBlock HorizontalAlignment="Left" Margin="27,809,0,0" TextWrapping="Wrap" Text="Длина змейки от: до:" VerticalAlignment="Top" Width="369"/>                             <TextBox x:Name="TextBox_MinLength" InputScope="Number" HorizontalAlignment="Left" Height="72" Margin="10,834,0,-17" TextWrapping="Wrap" Text="3" VerticalAlignment="Top" Width="101"/>                             <TextBox x:Name="TextBox_MaxLength" InputScope="Number" HorizontalAlignment="Left" Height="67" TextWrapping="Wrap" Text="10" VerticalAlignment="Top" Width="100" Margin="114,834,0,-17"/>                             <Button Content="Ok" HorizontalAlignment="Left" Margin="286,836,0,-19" VerticalAlignment="Top" Width="93" Click="Event_Button_Click_MaxLength"/>                                                          <!-- Горизонтакльное /  вертикальное расположение -->                             <TextBlock HorizontalAlignment="Left" Margin="28,905,0,0" TextWrapping="Wrap" Text="Повернуть матрицу" VerticalAlignment="Top" Width="352"/>                             <ToggleButton x:Name="ToggleButton_Turn" Content="Вертикально" HorizontalAlignment="Left" Margin="10,932,0,0" VerticalAlignment="Top" Width="371" Click="Event_Button_Click_Turn"/>                                                 </Grid>                     </ScrollViewer>                 </Grid> 

В третьем элементе остались последние 4 настройки: выбор языка, цвета и задание цвета первому элементу, фону, градиента для змейки. Так же все находится в ScrollViewer для вертикальной прокрутки. Однако тут пришлось использовать один нестандартный элемент управления, а именно ColorPicker. Его можно найти в дополнительной библиотеке элементов с названием Coding4Fun.

Как установить Coding4Fun

У меня последние пару недель с нугет проблемы, поэтому качал вручную.
Переходим по ссылке.
Нажимаем на большую красную кнопку с надписью «Via CodePlex Current Release Zip».
Качаем архив с именем «Coding4Fun.Toolkit (Windows Phone 8).zip».
Из архива копируем файл с именем «Coding4Fun.Toolkit.Controls.dll» к себе в проект.
Заходим в проект в папочку «References». Жмем на нее правой кнопкой — Добавить ссылку — Справа внизу выбираем Обзор… Находим нашу библиотеку и жмем ОК.
Заходим в Панель элементов. правой кнопкой где угодно в ее приделах — Выбрать элементы… Выбираем вкладку Windows Phone Components. Справа внизу жмем обзор и снова выбираем Coding4Fun.Toolkit.Controls.dll. Новые элементы будут подсвечены. Смотрим, что б возле элемента ColorPicker была галочка.
Убедитесь, что в начале файла добавилась строчка

    xmlns:Controls="clr-namespace:Coding4Fun.Toolkit.Controls;assembly=Coding4Fun.Toolkit.Controls" 

Продолжим. Перетаскиваем ColorPicker с Панели элементов. Назначаем имя. Теперь выбирать цвет будем на одном элементе, а применять выбранный цвет разными кнопками к разным характеристикам матрицы.

                            <!-- Элемент выбора цвета. Codding4Fun -->                             <Controls:ColorPicker x:Name="ColorPicker" VerticalAlignment="Top" Height="360" Margin="10,154,10,0"/>                             <TextBlock HorizontalAlignment="Left" Margin="10,114,0,0" TextWrapping="Wrap" Text="Выбирете цвет" VerticalAlignment="Top" Width="412" Height="35"/> 

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

                            <!-- Выбор языка символов -->                             <StackPanel Margin="0,0,0,649" >                                 <!-- Всплывающее окно -->                                 <Popup  Name="Popup_ButtonDropDownSelectLanguage" Margin="0,0,10,0">                                     <StackPanel Margin="10,50,0,0" Background="DarkGray"  Width="393" Name="StackPanel_ButtonDropDownSelectLanguage">                                     </StackPanel>                                 </Popup>                                 <TextBlock TextWrapping="Wrap" Text="Выбирете язык символов"/>                                 <!-- Кнопка, отображающая выбранный язык. При нажатии на нее всплывает окно -->                                 <Button Margin="0,10,10,0" x:Name="Button_SelectLanguage" Content="Китайский"  Click="Event_Button_Click_SelectLanguage" Height="74" />                             </StackPanel> 

И еще пара кнопок по аналогии со вторым элементом панорамы.

Код. Третий элемент Panorama

            <!--Третий элемент Panorama-->             <phone:PanoramaItem >                 <Grid x:Name="LayoutRoot123" Background="Transparent" Margin="0,-32,-2,7" RenderTransformOrigin="0.500,0.500" >                     <ScrollViewer HorizontalScrollBarVisibility="Hidden" Margin="0,26,0,0" >                                              <Grid Margin="0,0,0,0" Height="984" >                             <!-- Выбор языка символов -->                             <StackPanel Margin="0,0,0,649" >                                 <!-- Всплывающее окно -->                                 <Popup  Name="Popup_ButtonDropDownSelectLanguage" Margin="0,0,10,0">                                     <StackPanel Margin="10,50,0,0" Background="DarkGray"  Width="393" Name="StackPanel_ButtonDropDownSelectLanguage">                                     </StackPanel>                                 </Popup>                                 <TextBlock TextWrapping="Wrap" Text="Выбирете язык символов"/>                                 <!-- Кнопка, отображающая выбранный язык. При нажатии на нее всплывает окно -->                                 <Button Margin="0,10,10,0" x:Name="Button_SelectLanguage" Content="Китайский"  Click="Event_Button_Click_SelectLanguage" Height="74" />                             </StackPanel>                                                          <!-- Элемент выбора цвета. Codding4Fun -->                             <Controls:ColorPicker x:Name="ColorPicker" VerticalAlignment="Top" Height="360" Margin="10,154,10,0"/>                             <TextBlock HorizontalAlignment="Left" Margin="10,114,0,0" TextWrapping="Wrap" Text="Выбирете цвет" VerticalAlignment="Top" Width="412" Height="35"/>                                                         <!-- Выбор фона матрицы -->                             <Button x:Name="Button_BackgroundColor" Content="Цвет фона" HorizontalAlignment="Left" Margin="10,533,0,0" VerticalAlignment="Top" RenderTransformOrigin="-0.404,-0.757" Width="412" Click="Event_Button_Click_ChangeBackground"/>                                                          <!-- Выбор цвета первого символа -->                             <Button x:Name="Button_FirstSymbolColor" Content="Цвет первого символа" HorizontalAlignment="Left" Margin="10,605,0,0" VerticalAlignment="Top" Width="412" Click="Event_Button_Click_FirstSymbolColor"/>                                                          <!-- Выбор цвета градиента змейки -->                             <TextBlock HorizontalAlignment="Left" Margin="10,682,0,0" TextWrapping="Wrap" Text="Выберите цвета градиента змейки" VerticalAlignment="Top" RenderTransformOrigin="-0.915,-1.222" Width="412"/>                             <Button x:Name="Button_GradientFrom" Content="От" HorizontalAlignment="Left" Margin="10,714,0,0" VerticalAlignment="Top" Width="180" Click="Event_Button_Click_GradientFrom"/>                             <Button x:Name="Button_GradientTo" Content="До" HorizontalAlignment="Left" Margin="245,714,0,0" VerticalAlignment="Top" Width="180" Click="Event_Button_Click_GradientTo"/>                         </Grid>                     </ScrollViewer>                 </Grid>             </phone:PanoramaItem> 

Код. MainPage.xaml

<phone:PhoneApplicationPage     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"     xmlns:UI="clr-namespace:Microsoft.Advertising.Mobile.UI;assembly=Microsoft.Advertising.Mobile.UI"     xmlns:Controls="clr-namespace:Coding4Fun.Toolkit.Controls;assembly=Coding4Fun.Toolkit.Controls"     x:Class="SE_Matrix_2d_v_4.MainPage"     mc:Ignorable="d"     d:DataContext="{d:DesignData SampleData/MainViewModelSampleData.xaml}"     FontFamily="{StaticResource PhoneFontFamilyNormal}"     FontSize="{StaticResource PhoneFontSizeNormal}"     Foreground="{StaticResource PhoneForegroundBrush}"     SupportedOrientations="Portrait"  Orientation="Portrait"     shell:SystemTray.IsVisible="False">      <!--LayoutRoot представляет корневую сетку, где размещается все содержимое страницы-->     <Grid x:Name="LayoutRoot" Background="Transparent">          <!-- ПРИМЕЧАНИЕ О ЛОКАЛИЗАЦИИ:             Чтобы локализовать отображаемые строки, скопируйте их значения в соответствующим образом названные             ключи в файле ресурсов нейтрального языка приложения (AppResources.resx), а затем             замените жестко заданное текстовое значение между кавычками атрибутов             на выражение привязки, указывающее на имя соответствующей строки.              Пример:                  Text="{Binding Path=LocalizedResources.ApplicationTitle, Source={StaticResource LocalizedStrings}}"              Данная привязка указывает на строковый ресурс шаблона с именем "ApplicationTitle".              Добавление поддерживаемых языков на вкладку "Свойства проекта" создает             новый RESX-файл для каждого языка, в котором могут храниться переведенные значения             строк пользовательского интерфейса. Привязка в этих примерах вызывает отрисовку             значений атрибутов из RESX-файла, соответствующего             CurrentUICulture приложения во время выполнения.          -->          <!--Элемент управления Panorama-->         <phone:Panorama Title="">             <phone:Panorama.Background>                 <ImageBrush />             </phone:Panorama.Background>              <!--Первый элемент Panorama-->             <phone:PanoramaItem >                 <!--Тут создается и отображается матрица-->                 <Grid x:Name="LayoutRootSecond" Background="Black" Margin="0,-32,-2,7" RenderTransformOrigin="0.500,0.500" Tap="Event_Grid_Tap_LayoutRoot"/>             </phone:PanoramaItem>              <!--Второй элемент Panorama-->             <phone:PanoramaItem>                     <Grid x:Name="LayoutRootThierd" Grid.Column="1" Background="Transparent" Margin="0, 0,-2,7" RenderTransformOrigin="0.500,0.500" >                     <ScrollViewer  HorizontalScrollBarVisibility="Auto"  >                         <Grid x:Name="Grid_SettingsRight" Grid.Column="1" Background="Transparent" Margin="0, 0,-2,7" RenderTransformOrigin="0.500,0.500" >                             <!-- Скорость падения змейки в мс/ Скорость смены символов в мс -->                             <TextBlock HorizontalAlignment="Left" Margin="28,3,0,0" TextWrapping="Wrap" Text="Скорость смены символов в мс" VerticalAlignment="Top" Width="352"/>                             <TextBox x:Name="TextBox_SppeedFrom" InputScope="Number" HorizontalAlignment="Left" Height="67" TextWrapping="Wrap" Text="20" VerticalAlignment="Top" Width="100" Margin="9,28,0,0"/>                             <TextBox x:Name="TextBox_SppeedTo" InputScope="Number" HorizontalAlignment="Left" Height="67" TextWrapping="Wrap" Text="40" VerticalAlignment="Top" Width="100" Margin="114,28,0,0"/>                             <Button x:Name="Button_SpeedApplay" Content=" Ok " HorizontalAlignment="Left" Height="65" Margin="288,30,0,0" VerticalAlignment="Top" Click="Event_Button_Click_SpeedApplay"/>                              <!-- Количество змеек в очереди -->                             <TextBlock HorizontalAlignment="Left" Margin="28,95,0,0" TextWrapping="Wrap" Text="Количество змеек в очереди" VerticalAlignment="Top" RenderTransformOrigin="-0.256,0.233" Width="352"/>                             <TextBox x:Name="TextBox_CountQueue" InputScope="Number" HorizontalAlignment="Left" Height="67" Margin="10,127,0,0" TextWrapping="Wrap" Text="5" VerticalAlignment="Top" Width="101" RenderTransformOrigin="0.49,-0.049"/>                             <Button x:Name="Button_CountQueue" Content=" Ok " HorizontalAlignment="Left" Margin="287,127,0,0" VerticalAlignment="Top" Click="Event_Button_Click_CountQueue" RenderTransformOrigin="1.474,0.483" Height="67"/>                              <!-- Количество змеек за нажатие -->                             <TextBlock HorizontalAlignment="Left" Margin="28,194,0,0" TextWrapping="Wrap" Text="Количество змеек за нажатие" VerticalAlignment="Top" Width="352"/>                             <TextBox x:Name="TextBox_СountSimultaneously" InputScope="Number" HorizontalAlignment="Left" Height="72" Margin="10,221,0,0" TextWrapping="Wrap" Text="1" VerticalAlignment="Top" Width="101"/>                             <Button x:Name="Button_СountSimultaneously" Content=" Ok " HorizontalAlignment="Left" Margin="288,221,0,0" VerticalAlignment="Top" Click="Event_Button_Click_СountSimultaneously" RenderTransformOrigin="1.474,0.483"/>                              <!-- Размер шрифта -->                             <TextBlock HorizontalAlignment="Left" Margin="27,293,0,0" TextWrapping="Wrap" Text="Размер шрифта (+ - [n])" VerticalAlignment="Top" Width="352"/>                             <TextBox x:Name="TextBox_FontSize" InputScope="Default" HorizontalAlignment="Left" Height="72" Margin="9,320,0,0" TextWrapping="Wrap" Text="-2" VerticalAlignment="Top" Width="101"/>                             <Button x:Name="Button_FontSize" Content=" Ok " HorizontalAlignment="Left" Margin="288,320,0,0" VerticalAlignment="Top" Click="Event_Button_Click_FontSize" RenderTransformOrigin="1.474,0.483"/>                              <!-- Количество смены символов в ячейке -->                             <TextBlock HorizontalAlignment="Left" Margin="28,392,0,0" TextWrapping="Wrap" Text="Количество смены символов" VerticalAlignment="Top" Width="352"/>                             <TextBox x:Name="TextBox_CountSymbol" InputScope="Number" HorizontalAlignment="Left" Height="72" Margin="10,419,0,0" TextWrapping="Wrap" Text="3" VerticalAlignment="Top" Width="101"/>                             <Button x:Name="Button_CountSymbol" Content=" Ok " HorizontalAlignment="Left" Margin="288,419,0,0" VerticalAlignment="Top" Click="Event_Button_Click_CountSymbol" RenderTransformOrigin="1.474,0.483"/>                              <!-- Сатрт / Стоп анимация -->                             <TextBlock x:Name="TextBlock_OnOff" HorizontalAlignment="Left" Margin="28,491,0,0" TextWrapping="Wrap" Text="Вкл/Выкл анимацию" VerticalAlignment="Top" Width="352"/>                             <ToggleButton x:Name="Button_Stop" Content="Stop" HorizontalAlignment="Left" Margin="214,523,0,0" VerticalAlignment="Top" Click="Event_Button_Click_Stop" Width="180"/>                             <ToggleButton x:Name="Button_Start" Content="Start" HorizontalAlignment="Left" Margin="10,523,0,0" VerticalAlignment="Top" Click="Event_Button_Click_Start" Width="180"/>                                                          <!-- Очистка экрана -->                             <TextBlock HorizontalAlignment="Left" Margin="28,605,0,0" TextWrapping="Wrap" Text="Хотите очистит экран?" VerticalAlignment="Top" Width="352"/>                             <Button Content=" YES " HorizontalAlignment="Left" Margin="10,632,0,0" VerticalAlignment="Top" Width="371" Click="Event_Button_Click_Clear"/>                              <!-- Размер клетки для символа -->                             <TextBlock HorizontalAlignment="Left" Margin="27,709,0,0" TextWrapping="Wrap" Text="Размер клетки для символа" VerticalAlignment="Top" Width="369"/>                             <TextBox x:Name="TextBox_ElementSize" InputScope="Default" HorizontalAlignment="Left" Height="72" Margin="10,734,0,-17" TextWrapping="Wrap" Text="-6" VerticalAlignment="Top" Width="101"/>                             <Button Content="Ok" HorizontalAlignment="Left" Margin="286,736,0,-19" VerticalAlignment="Top" Width="93" Click="Event_Button_Click_ElementSize"/>                              <!-- Длина змейки -->                             <TextBlock HorizontalAlignment="Left" Margin="27,809,0,0" TextWrapping="Wrap" Text="Длина змейки от: до:" VerticalAlignment="Top" Width="369"/>                             <TextBox x:Name="TextBox_MinLength" InputScope="Number" HorizontalAlignment="Left" Height="72" Margin="10,834,0,-17" TextWrapping="Wrap" Text="3" VerticalAlignment="Top" Width="101"/>                             <TextBox x:Name="TextBox_MaxLength" InputScope="Number" HorizontalAlignment="Left" Height="67" TextWrapping="Wrap" Text="10" VerticalAlignment="Top" Width="100" Margin="114,834,0,-17"/>                             <Button Content="Ok" HorizontalAlignment="Left" Margin="286,836,0,-19" VerticalAlignment="Top" Width="93" Click="Event_Button_Click_MaxLength"/>                                                          <!-- Горизонтакльное /  вертикальное расположение -->                             <TextBlock HorizontalAlignment="Left" Margin="28,905,0,0" TextWrapping="Wrap" Text="Повернуть матрицу" VerticalAlignment="Top" Width="352"/>                             <ToggleButton x:Name="ToggleButton_Turn" Content="Вертикально" HorizontalAlignment="Left" Margin="10,932,0,0" VerticalAlignment="Top" Width="371" Click="Event_Button_Click_Turn"/>                                                 </Grid>                     </ScrollViewer>                 </Grid>                                  </phone:PanoramaItem>              <!--Третий элемент Panorama-->             <phone:PanoramaItem >                 <Grid x:Name="LayoutRoot123" Background="Transparent" Margin="0,-32,-2,7" RenderTransformOrigin="0.500,0.500" >                     <ScrollViewer HorizontalScrollBarVisibility="Hidden" Margin="0,26,0,0" >                                              <Grid Margin="0,0,0,0" Height="984" >                             <!-- Выбор языка символов -->                             <StackPanel Margin="0,0,0,649" >                                 <!-- Всплывающее окно -->                                 <Popup  Name="Popup_ButtonDropDownSelectLanguage" Margin="0,0,10,0">                                     <StackPanel Margin="10,50,0,0" Background="DarkGray"  Width="393" Name="StackPanel_ButtonDropDownSelectLanguage">                                     </StackPanel>                                 </Popup>                                 <TextBlock TextWrapping="Wrap" Text="Выбирете язык символов"/>                                 <!-- Кнопка, отображающая выбранный язык. При нажатии на нее всплывает окно -->                                 <Button Margin="0,10,10,0" x:Name="Button_SelectLanguage" Content="Китайский"  Click="Event_Button_Click_SelectLanguage" Height="74" />                             </StackPanel>                                                          <!-- Элемент выбора цвета. Codding4Fun -->                             <Controls:ColorPicker x:Name="ColorPicker" VerticalAlignment="Top" Height="360" Margin="10,154,10,0"/>                             <TextBlock HorizontalAlignment="Left" Margin="10,114,0,0" TextWrapping="Wrap" Text="Выбирете цвет" VerticalAlignment="Top" Width="412" Height="35"/>                                                         <!-- Выбор фона матрицы -->                             <Button x:Name="Button_BackgroundColor" Content="Цвет фона" HorizontalAlignment="Left" Margin="10,533,0,0" VerticalAlignment="Top" RenderTransformOrigin="-0.404,-0.757" Width="412" Click="Event_Button_Click_ChangeBackground"/>                                                          <!-- Выбор цвета первого символа -->                             <Button x:Name="Button_FirstSymbolColor" Content="Цвет первого символа" HorizontalAlignment="Left" Margin="10,605,0,0" VerticalAlignment="Top" Width="412" Click="Event_Button_Click_FirstSymbolColor"/>                                                          <!-- Выбор цвета градиента змейки -->                             <TextBlock HorizontalAlignment="Left" Margin="10,682,0,0" TextWrapping="Wrap" Text="Выберите цвета градиента змейки" VerticalAlignment="Top" RenderTransformOrigin="-0.915,-1.222" Width="412"/>                             <Button x:Name="Button_GradientFrom" Content="От" HorizontalAlignment="Left" Margin="10,714,0,0" VerticalAlignment="Top" Width="180" Click="Event_Button_Click_GradientFrom"/>                             <Button x:Name="Button_GradientTo" Content="До" HorizontalAlignment="Left" Margin="245,714,0,0" VerticalAlignment="Top" Width="180" Click="Event_Button_Click_GradientTo"/>                         </Grid>                     </ScrollViewer>                 </Grid>             </phone:PanoramaItem>         </phone:Panorama>          <!--Раскомментируйте, чтобы увидеть сетку выравнивания и выровнять             элементы управления по общим границам.  Верхнее поле изображения равно -32 пикселя, чтобы             осталось место для области уведомлений. Установите его равным 0 (или вообще удалите поле),             если область уведомлений скрыта.              Перед сдачей приложения удалите этот код XAML и само изображение.-->         <!--<Image Source="/Assets/AlignmentGrid.png" VerticalAlignment="Top" Height="800" Width="480" Margin="0" Grid.Row="0" Grid.RowSpan="2" IsHitTestVisible="False" />-->      </Grid> </phone:PhoneApplicationPage> 

Внешне настройки выглядят так:

MainPage.xaml.cs

Первым делом создаем свойства класса, которые будут отвечать за настройки:

Код. Свойства класса

        /* ****************************** Свойства класса ****************************** */         // Случайное число         Random random = new Random();          // Количество змеек после нажатия на экран в очереди         int iteration = 5;          // Количество одновременно появляющихся змеек после нажатия         int countSimultaneously = 3;          // Скорость смены символов         int speedFrom = 20;         int speedTo = 40;          // Размер клетки для символа         int addingSize = -6;          // Итоговый размер шрифта         int fontSize;          // Минимальная и максимальная длина змейки         int minLength = 10;         int maxLength = 15;          // Получаем расширение экрана         double ScreenWidth = System.Windows.Application.Current.Host.Content.ActualWidth - 60;         double ScreenHeight = System.Windows.Application.Current.Host.Content.ActualHeight - 100;                  // Коеффициент, отвечающий за количесвто ячеек и частично за размер шрифта         int kolich = 30;          // Размер шрифта задается по формуле kolich + addingFontSize.         int addingFontSize = -2;          // Количество смены символов в ячейке         int countSymbol = 3;          // Включить (false), выключить (true) матрицу         bool flagOnOff = false;          // Включить (false), выключить (true) "поворот экрана"         bool turnOnOff = true;          // Количество строк и столбцов         int countWidth = 10;         int countHeight = 10;          // Словарь, в котором хранятся идентификаторы языка и соответствующие ему ASCII коды символов         Dictionary<string, int[]> languages = new Dictionary<string, int[]>();          // Задаю язык по-умолчанию         string actualLanguage = "Русский";          // Флаг, отвечающий за показывать (true) / не показывать (false) всплывающее окно (PopUp) при выборе языка         bool flagShowLanguages = true;          // Цвет фона матрицы, ARGB         Dictionary<string, int> colorMatrixBackground = new Dictionary<string, int>();          // Цвет первого символа, ARGB         Dictionary<string, int> colorFirstSymbol = new Dictionary<string, int>();          // Цвет градиента змейки от (второй символ) - до (последний символ), ARGB         Dictionary<string, int> gradientFrom = new Dictionary<string, int>();         Dictionary<string, int> gradientTo = new Dictionary<string, int>(); 

Рассмотри конструктор класса:

Код. Конструктор класса

        // Конструктор         public MainPage()         {             InitializeComponent();              // Вызываем функцию настройки начальных значений цветов фона, символов и т.д.             BeginColorSettings();              // Инициализируем список доступных языков, а также соответствующие им ASCII коды символов             ListLanguages();              // Количество строк и столбцов             this.countWidth = (int)Math.Round(ScreenWidth / (kolich + addingSize)) + Math.Abs(addingSize);             this.countHeight = (int)Math.Round(ScreenHeight / (kolich + addingSize)) + 5 + Math.Abs(addingSize);              // Создание сетки элементов, в которой будет сыпаться матрица             CreateElement();              // Подсвечиваем кнопку Вкл или Выкл,  зависит от флага             if (this.flagOnOff)             {                 Button_Stop.Background = new SolidColorBrush(Colors.Cyan);                 Button_Start.Background = new SolidColorBrush(Colors.Black);             }             else             {                 Button_Stop.Background = new SolidColorBrush(Colors.Black);                 Button_Start.Background = new SolidColorBrush(Colors.Cyan);             }              // Меняем цвет фона матрицы             ChangeBackground();         } 

Давайте начнем с выбора цвета. Для начала инициализируем настройки по умолчанию в методе BeginColorSettings();

Код. BeginColorSettings

        // Начальные настройки цветов фона, символов и т.д         private void BeginColorSettings()         {             // Задаем начальный цвет фона матрицы             colorMatrixBackground["A"] = 0;             colorMatrixBackground["R"] = 0;             colorMatrixBackground["G"] = 0;             colorMatrixBackground["B"] = 0;              // Задаем начальный цвет первого символа             colorFirstSymbol["A"] = 255;             colorFirstSymbol["R"] = 248;             colorFirstSymbol["G"] = 248;             colorFirstSymbol["B"] = 255;              // Задаем начальный цвет градиента от (второго символа в змейке)             gradientFrom["A"] = 255;             gradientFrom["R"] = 1;             gradientFrom["G"] = 255;             gradientFrom["B"] = 1;              // Задаем начальный цвет градиента до (последнего символа в змейке)             gradientTo["A"] = 0;             gradientTo["R"] = 0;             gradientTo["G"] = 0;             gradientTo["B"] = 0;         } 

Цвет фона матрицы

Задаем цвет фона. Просто присваиваем соответствующему атрибуту цвет, состоящий из компонент ARGB. Почему четыре составляющие? Прозрачность (А) нам будет нужна для создания эффекта затухания.

Код. ChangeBackground

        // Метод изменения цвета фона матрицы. По умолчанию черный.         private void ChangeBackground()         {             // Задаю цвет фона матрицы             LayoutRootSecond.Background = new SolidColorBrush(new Color()             {                 A = (byte)(colorMatrixBackground["A"]) /*Opacity*/,                 R = (byte)(colorMatrixBackground["R"]) /*Red*/,                 G = (byte)(colorMatrixBackground["G"]) /*Green*/,                 B = (byte)(colorMatrixBackground["B"]) /*Blue*/             });         } 

Однако это просто метод. Для того, что б цвет действительно поменялся, нужно забрать его из контролла ColorPicker, присвоить свойству и вызвать метод ChangeBackground:

Код. Event_Button_Click_ChangeBackground

        // Меняем цвет фона матрицы         private void Event_Button_Click_ChangeBackground(object sender, RoutedEventArgs e)         {             // Передаем в свойство класса colorMatrixBackground выбранный цвет из элемента ColorPicker для фона матрицы             colorMatrixBackground["A"] = ColorPicker.Color.A;             colorMatrixBackground["R"] = ColorPicker.Color.R;             colorMatrixBackground["G"] = ColorPicker.Color.G;             colorMatrixBackground["B"] = ColorPicker.Color.B;              // Задаем выбранный цвет фона матрицы соответствующей кнопке             Button_BackgroundColor.Background = new SolidColorBrush(new Color()             {                 A = (byte)(colorMatrixBackground["A"]) /*Opacity*/,                 R = (byte)(colorMatrixBackground["R"]) /*Red*/,                 G = (byte)(colorMatrixBackground["G"]) /*Green*/,                 B = (byte)(colorMatrixBackground["B"]) /*Blue*/             });              // Задаем выбранный цвет фона матрицы             ChangeBackground();         } 

Цвет первого символа змейки

Изменим цвет первого символа змейки. Первый символ змейки вызывается в методе RandomElementQ_Async асинхронно:

                    // Вызываем на прорисовку первый, самый яркий падающий элемент. Асинхронно.                     // colorFirstSymbol["A"]. Цвет задается через настройку.                                        await Change(element, timeOut, colorFirstSymbol); 

Код. Event_Button_Click_FirstSymbolColor

        // Изменение цвета первого символа         private void Event_Button_Click_FirstSymbolColor(object sender, RoutedEventArgs e)         {             // Передаем в свойство класса colorFirstSymbol выбранный цвет из элемента ColorPicker для фона матрицы             colorFirstSymbol["A"] = ColorPicker.Color.A;             colorFirstSymbol["R"] = ColorPicker.Color.R;             colorFirstSymbol["G"] = ColorPicker.Color.G;             colorFirstSymbol["B"] = ColorPicker.Color.B;              // Задаем выбранный цвет фона матрицы соответствующей кнопке             Button_FirstSymbolColor.Background = new SolidColorBrush(new Color()             {                 A = (byte)(colorFirstSymbol["A"]) /*Opacity*/,                 R = (byte)(colorFirstSymbol["R"]) /*Red*/,                 G = (byte)(colorFirstSymbol["G"]) /*Green*/,                 B = (byte)(colorFirstSymbol["B"]) /*Blue*/             });         } 

Задание цветов для градиента

Ну вот и добрались до градиента. Первое, что нужно сделать — это в обработчиках событий соответствующих кнопок сохранить цвет в свойства класса:

Код. Event_Button_Click_Gradient

        // Настройки. Задаем градиент змейки. Цвет второго символа.         private void Event_Button_Click_GradientFrom(object sender, RoutedEventArgs e)         {             // Передаем в свойство класса gradientFrom выбранный цвет из элемента ColorPicker для фона матрицы             gradientFrom["A"] = ColorPicker.Color.A;             gradientFrom["R"] = ColorPicker.Color.R;             gradientFrom["G"] = ColorPicker.Color.G;             gradientFrom["B"] = ColorPicker.Color.B;              // Задаем выбранный цвет градиента от змейки соответствующей кнопке             Button_GradientFrom.Background = new SolidColorBrush(new Color()             {                 A = (byte)(gradientFrom["A"]) /*Opacity*/,                 R = (byte)(gradientFrom["R"]) /*Red*/,                 G = (byte)(gradientFrom["G"]) /*Green*/,                 B = (byte)(gradientFrom["B"]) /*Blue*/             });         }           / Настройки. Задаем градиент змейки. Цвет последнего символа.         private void Event_Button_Click_GradientTo (object sender, RoutedEventArgs e)         {             // Передаем в свойство класса gradientTo выбранный цвет из элемента ColorPicker для фона матрицы             gradientTo["A"] = ColorPicker.Color.A;             gradientTo["R"] = ColorPicker.Color.R;             gradientTo["G"] = ColorPicker.Color.G;             gradientTo["B"] = ColorPicker.Color.B;              // Задаем выбранный цвет градиента до змейки соответствующей кнопке             Button_GradientTo.Background = new SolidColorBrush(new Color()             {                 A = (byte)(gradientTo["A"]) /*Opacity*/,                 R = (byte)(gradientTo["R"]) /*Red*/,                 G = (byte)(gradientTo["G"]) /*Green*/,                 B = (byte)(gradientTo["B"]) /*Blue*/             });         }      

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

Код. RandomElementQ_Async и Change

Меняем

//int greenCoefficient = (int)Math.Round(255 / (double)(count + 1)) - 1; 

на

                    int A_Coefficient = (int)Math.Round((gradientFrom["A"] - 10) / (double)(count + 1)) - 1;                     int R_Coefficient = (int)Math.Round((gradientFrom["R"] - gradientTo["R"]) / (double)(count + 1)) - 1;                     int G_Coefficient = (int)Math.Round((gradientFrom["G"] - gradientTo["G"]) / (double)(count + 1)) - 1;                     int B_Coefficient = (int)Math.Round((gradientFrom["B"] - gradientTo["B"]) / (double)(count + 1)) - 1; 

А так же перед вызовом Task dsvv = Change(previousElement, timeOut, SymbolColor); добавляем:

                            // Вызываем извлеченные элементы                             // (greenCoefficient * (k + 1)) - 20 Высчитываем яркость так, что б разница между первым и последним была на всех змейках одинаковая                             // и равномерно распределялась независимо от ее длины(количества элементов)                             SymbolColor["A"] = (gradientFrom["A"] - ((i - k) * A_Coefficient));                             SymbolColor["R"] = (gradientFrom["R"] - ((i - k) * R_Coefficient));                             SymbolColor["G"] = (gradientFrom["G"] - ((i - k) * G_Coefficient));                             SymbolColor["B"] = (gradientFrom["B"] - ((i - k) * B_Coefficient)); 

И меняем определение метода Change, где вместо int Opacity ставим Dictionary<string, int> SymbolColor:

 // Метод изменения символов в заданном элеменете         public async Task Change(TextBlock element, int timeOut, Dictionary<string, int> SymbolColor) 

А внутри этого метода задаем цвет символа с помощью новых значений. Меняем

            // Формируем нужный цвет с заданной яркостью             SolidColorBrush NewColor = new SolidColorBrush(new Color()             {                 A = (byte)(255) /*Opacity*/,                 R = (byte)(0) /*Red*/,                 G = (byte)(Opacity) /*Green*/,                 B = (byte)(0) /*Blue*/             }); 

на

            // Формируем нужный цвет с заданной яркостью             SolidColorBrush NewColor = new SolidColorBrush(new Color()             {                 A = (byte)(SymbolColor["A"]) /*Opacity*/,                 R = (byte)(SymbolColor["R"]) /*Red*/,                 G = (byte)(SymbolColor["G"]) /*Green*/,                 B = (byte)(SymbolColor["B"]) /*Blue*/             }); 

Выбор языка

С цветами разобрались. Теперь давайте решим вопрос с выбором языка. В конструкторе класса мы вызывали метод ListLanguages для инициализации доступных языков. Рассмотрим его более подробно:

Код. ListLanguages

        // Заполняем словарь идентификаторами языка и соответствующие ему ASCII коды символов         public void ListLanguages()         {             // Добавляем в словарь ключь -  название языка и значение -  массив, состоящий из ASCII кодов символов.             languages.Add("Матрица", new int[] { 64, 127 });             languages.Add("Китаский", new int[] { 19968, 20223 });             languages.Add("Английский", new int[] { 64, 127 });             languages.Add("Цифры", new int[] { 48, 57 });             languages.Add("Случайные символы", new int[] { 0, 1000 });             languages.Add("Русский", new int[] { 1040, 1103 });              // Добавляем языки в всплывающую панель для возможности их выбора             foreach (var language in languages)             {                 // Создаю кнопку                 Button newLang = new Button();                  // Задаю надпись кнопки, соответствует языку                 newLang.Content = language.Key.ToString();                  // Горизонтальное выравнивание                 newLang.HorizontalAlignment = HorizontalAlignment.Stretch;                  // Толщина рамки                 newLang.BorderThickness = new Thickness(1);                  // Смещение                 newLang.Margin = new Thickness(0,0,0,0);                  // Событие, при нажатии на кнопку. Одно на все.                 newLang.Click += Event_Button_Click_SelectLanguageUpdate;                  // Добавляю созданую и настроенную кнопку в всплывающее окно                 StackPanel_ButtonDropDownSelectLanguage.Children.Add(newLang);             }         } 

Теперь добавляем обработчик кнопки, в которой показывается выбранный язык и при нажатии на которую появляется всплывающее окно:

Код. Event_Button_Click_SelectLanguage

        // Кнопка, в которой показывается текущее выбранное значение языка. при нажатии на нее всплывает меню для выбора другого языка.         private void Event_Button_Click_SelectLanguage(object sender, RoutedEventArgs e)         {             // Показывать (true) / не показывать (false) всплывающее окно (PopUp) при выборе языка             if (flagShowLanguages)             {                 // Показать всплывающее окно                 Popup_ButtonDropDownSelectLanguage.IsOpen = true;                 flagShowLanguages = false;             }             else             {                 // Скрыть всплывающее окно                 Popup_ButtonDropDownSelectLanguage.IsOpen = false;                 flagShowLanguages = true;             }         } 

В сплывающем окне находятся кнопки, при нажатии на которые и выбирается нужный язык. У всех кнопок назначен один и тот же обработчик событий, который определяет контент кнопки, который и является ключом в словаре для выбора языка. Задаем значение выбранного языка в свойство класса actualLanguage:

Код. Event_Button_Click_SelectLanguageUpdate

        // Всплывающее меню выбора языка.         private void Event_Button_Click_SelectLanguageUpdate(object sender, RoutedEventArgs e)         {             // Если нажата кнопка выбора языка, но другой язык не выбран, то при повторном нажатии меню свернется.              if (!flagShowLanguages)             {                 // Скрыть всплывающее окно                 Popup_ButtonDropDownSelectLanguage.IsOpen = false;                 flagShowLanguages = true;             }              // Получаем название кнопки, которую нажали             string newLanguagr = (sender as Button).Content.ToString();              // Обновляем название кнопки, отображающей выбранный язык             Button_SelectLanguage.Content = newLanguagr;              // Задаем значение языка, в котором выбирать символы случайным образом             this.actualLanguage = newLanguagr;         } 

Теперь все готово, для того, что б можно было выбрать случайный символ из заданного диапазона. Напишем метод RandomActualSymbol, который и будет возвращать случайный символ:

Код. RandomActualSymbol

        // Вызываем эту функцию везде, где нужно показать случайный символ из выбранного языка.         public string RandomActualSymbol()         {             // Получаем массив по ключу, содержащий ASCII коды символов языка, заданного в actualLanguage             int[] sd = (languages[actualLanguage]);              // Выбираем случайнфй символ в диапазоне от первого до последнего символа в заданом языке             return char.ConvertFromUtf32(this.random.Next((int)sd.GetValue(0), (int)sd.GetValue(1)));         } 

И подставим вызов этого метода везде, где нужно задать символ. Например, в методе Change:

                // Каждый раз разный символ из заданного диапазона                 element.Text = RandomActualSymbol();    

Старт / Стоп

Тут все очень просто. В зависимости от флага flagOnOff, который задан как свойство класса завершаем циклы, в которых происходит обработка непосредственно самой матрицы.
Задаем обработчики событий кнопок «Старт» и «Стоп», которые просто меняют состояние флага на противоположный:

Код. Event_Button_Click_Stop и Event_Button_Click_Start

        // Настройки. Выключаем возможность анимирования змеек         private void Event_Button_Click_Stop(object sender, RoutedEventArgs e)         {             this.flagOnOff = true;              // Если flagOnOff в true то подсвечиваем кнопку Stop             if (this.flagOnOff)             {                 Button_Stop.Background = new SolidColorBrush(Colors.Cyan);                 Button_Start.Background = new SolidColorBrush(Colors.Black);             }         }          // Настройки. Включаем возможность анимирования змеек         private void Event_Button_Click_Start(object sender, RoutedEventArgs e)         {             this.flagOnOff = false;              // Если flagOnOff в false то подсвечиваем кнопку Start             if (!this.flagOnOff)             {                 Button_Stop.Background = new SolidColorBrush(Colors.Black);                 Button_Start.Background = new SolidColorBrush(Colors.Cyan);             }         } 

И добавляем внутри нескольких циклов простое условие

 if (flagOnOff) break; 

А именно в циклах методов Event_Grid_Tap_LayoutRoot, RandomElementQ_Async, Change:

Код. Остановка матрицы

В Event_Grid_Tap_LayoutRoot:

            // Количество одновременно появляющихся змеек после нажатия             for (int i = 0; i < countSimultaneously; i++)             {                 // Останавливаем анимацию                 if (flagOnOff) break; 

В RandomElementQ_Async тут:

             // Цикл формирует змейку заданной длины length             for (int i = 0; i <= length; i++)             {                 // Останавливаем анимацию                 if (flagOnOff) break; 

и тут:

                    // Перебираем все  элементы, составляющие змейку на данном этапе. С каждым циклом она увеличивается, пока не достигнет нужной длины.                     for (int k = 0; k <= i; k++)                     {                                                // Останавливаем анимацию                         if (flagOnOff) break; 

В Change:

            // Количество смены символов в каждой ячейке             for (int i = 0; i < countSymbol; i++)             {                 // Останавливаем анимацию                 if (flagOnOff) break; 

Почему аж в четырех местах? Если змеек мало, то все нормально. Но если количество змеек неприлично большое, например, 50+, то матрица останавливается с заметными тормозами. А так мы останавливаем непосредственно каждый элемент, принимающий участие в работе механизма матрицы.
Ну и напоследок добавим красоты, для задания цвета кнопки, которая сейчас нажата. В конструкторе за это отвечает этот код:

            // Подсвечиваем кнопку Вкл или Выкл,  зависит от флага             if (this.flagOnOff)             {                 Button_Stop.Background = new SolidColorBrush(Colors.Cyan);                 Button_Start.Background = new SolidColorBrush(Colors.Black);             }             else             {                 Button_Stop.Background = new SolidColorBrush(Colors.Black);                 Button_Start.Background = new SolidColorBrush(Colors.Cyan);             } 

Точнее сказать, задания цвета кнопки при инициализации приложения.

Очистка экрана

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

Код. Event_Button_Click_Clear

        // Настройки. Очистка экрана         private void Event_Button_Click_Clear(object sender, RoutedEventArgs e)         {             // Перебираем сетку ячеек и устанавливаем в каждой ячейке как символ - пустоту             for ( int i = 0; i < countWidth; i++)             {                 for (int j = 0; j < countHeight; j++)                 {                     // Формируем имя элемента, который будем очищать                     string elementName = "TB_" + i + "_" + j;                      // Получаем элемент по его имени                     object wantedNode = LayoutRoot.FindName(elementName);                     TextBlock element = (TextBlock)wantedNode;                      // Очищаем значение                     element.Text = "";                 }             }         } 

Горизонтальная / Вертикальная ориентация

Опять все исходит от флага turnOnOff. Что мы делаем? Останавливаем матрицу. Меняем надпись на кнопке. Меняем местами количество строк и столбцов. Удаляем матрицу. Создаем матрицу снова, вызывая метод CreateElement:

Код. Event_Button_Click_Turn

        // Настройки. Вериткальная / горизонтальная матрица         private void Event_Button_Click_Turn(object sender, RoutedEventArgs e)         {             // Включить (true), выключить (false) "поворот экрана"             if (turnOnOff)             {                 // Сохраняем значение false в свойство класса turnOnOff                 this.turnOnOff = false;                  // Надпись на конопке с именем ToggleButton_Turn меняю на Горизонтально                 ToggleButton_Turn.Content = "Горизонтально";                  // Количество строк и столбцов. Инвертируем для горизонтали.                 this.countHeight = (int)Math.Round(ScreenWidth / (kolich + addingSize)) + 5 + Math.Abs(addingSize);                 this.countWidth = (int)Math.Round(ScreenHeight / (kolich + addingSize)) + 5 + Math.Abs(addingSize);             }             else             {                 // Сохраняем значение true в свойство класса turnOnOff                 this.turnOnOff = true;                  // Надпись на конопке с именем ToggleButton_Turn меняю на Вертикально                 ToggleButton_Turn.Content = "Вертикально";                  // Количество строк и столбцов. Возвращаем для вертикали                 this.countWidth = (int)Math.Round(ScreenWidth / (kolich + addingSize)) + Math.Abs(addingSize);                 this.countHeight = (int)Math.Round(ScreenHeight / (kolich + addingSize)) + 5 + Math.Abs(addingSize);             }              // Останавливаем матрицу             this.flagOnOff = true;              // Удаляем матрицу (сами ячейки)             LayoutRootSecond.Children.Clear();              // Перерисовываем ячейки заново с новыми параметрами             CreateElement();              // Включаем матрицу             this.flagOnOff = false;         } 

Изменение размера матрицы

Логика схожа с поворотом. Единственная разница в том, что мы не меняем местами количество строк и столбцов, а добавляем к расчету количества строк и столбцов коэффициент, введенный пользователем:

Код. Event_Button_Click_ElementSize

        // Настройки. Размер клетки для символа         private void Event_Button_Click_ElementSize(object sender, RoutedEventArgs e)         {             // Сохраняем значение их соответствующего TextBox TextBox_ElementSize в свойство класса addingSize             this.addingSize = int.Parse(TextBox_ElementSize.Text.ToString());              // Количество строк и столбцов. Возвращаем для вертикали             this.countWidth = (int)Math.Round(ScreenWidth / (kolich + addingSize)) + Math.Abs(addingSize);             this.countHeight = (int)Math.Round(ScreenHeight / (kolich + addingSize)) + 5 + Math.Abs(addingSize);              // Останавливаем матрицу             this.flagOnOff = true;              // Удаляем матрицу (сами ячейки)             LayoutRootSecond.Children.Clear();              // Перерисовываем ячейки заново с новыми параметрами             CreateElement();              // Включаем матрицу             this.flagOnOff = false;         } 

Остальные настройки

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

Код. Event_Grid_Tap_LayoutRoot

Вместо статики

        // Событие при нажатии на эелемет Grid (на экран)         private void Event_Grid_Tap_LayoutRoot(object sender, System.Windows.Input.GestureEventArgs e)         {             // Количество одновременно появляющихся змеек после нажатия             for (int i = 0; i < 5; i++)             {                 // Останавливаем анимацию                 if (flagOnOff) break;                  Start();                  //Задержка между вызовами. Для красоты матрицы.                 Task.Delay(100);             }         } 

Делаем динамику:

        // Событие при нажатии на эелемет Grid (на экран)         private void Event_Grid_Tap_LayoutRoot(object sender, System.Windows.Input.GestureEventArgs e)         {             // Количество одновременно появляющихся змеек после нажатия             for (int i = 0; i < countSimultaneously; i++)             {                 // Останавливаем анимацию                 if (flagOnOff) break;                  Start();                  //Задержка между вызовами. Для красоты матрицы.                 Task.Delay(100);             }         } 

Код. MainPage.xaml.cs

using System; using System.Net; using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Navigation; using Microsoft.Phone.Controls; using Microsoft.Phone.Shell; using System.Windows.Media; using System.Threading.Tasks; using System.Diagnostics; using System.Collections.ObjectModel;  namespace SE_Matrix_2d_v_4 {     public partial class MainPage : PhoneApplicationPage     {         /* ****************************** Свойства класса ****************************** */         // Случайное число         Random random = new Random();          // Количество змеек после нажатия на экран в очереди         int iteration = 5;          // Количество одновременно появляющихся змеек после нажатия         int countSimultaneously = 3;          // Скорость смены символов         int speedFrom = 20;         int speedTo = 40;          // Размер клетки для символа         int addingSize = -6;          // Итоговый размер шрифта         int fontSize;          // Минимальная и максимальная длина змейки         int minLength = 10;         int maxLength = 15;          // Получаем расширение экрана         double ScreenWidth = System.Windows.Application.Current.Host.Content.ActualWidth - 60;         double ScreenHeight = System.Windows.Application.Current.Host.Content.ActualHeight - 100;                  // Коеффициент, отвечающий за количесвто ячеек и частично за размер шрифта         int kolich = 30;          // Размер шрифта задается по формуле kolich + addingFontSize.         int addingFontSize = -2;          // Количество смены символов в ячейке         int countSymbol = 3;          // Включить (false), выключить (true) матрицу         bool flagOnOff = false;          // Включить (false), выключить (true) "поворот экрана"         bool turnOnOff = true;          // Количество строк и столбцов         int countWidth = 10;         int countHeight = 10;          // Словарь, в котором хранятся идентификаторы языка и соответствующие ему ASCII коды символов         Dictionary<string, int[]> languages = new Dictionary<string, int[]>();          // Задаю язык по-умолчанию         string actualLanguage = "Русский";          // Флаг, отвечающий за показывать (true) / не показывать (false) всплывающее окно (PopUp) при выборе языка         bool flagShowLanguages = true;          // Цвет фона матрицы, ARGB         Dictionary<string, int> colorMatrixBackground = new Dictionary<string, int>();          // Цвет первого символа, ARGB         Dictionary<string, int> colorFirstSymbol = new Dictionary<string, int>();          // Цвет градиента змейки от (второй символ) - до (последний символ), ARGB         Dictionary<string, int> gradientFrom = new Dictionary<string, int>();         Dictionary<string, int> gradientTo = new Dictionary<string, int>();                  /* ****************************** Методы класса ****************************** */         // Конструктор         public MainPage()         {             InitializeComponent();              // Вызываем функцию настройки начальных значений цветов фона, символов и т.д.             BeginColorSettings();              // Инициализируем список доступных языков, а также соответствующие им ASCII коды символов             ListLanguages();              // Количество строк и столбцов             this.countWidth = (int)Math.Round(ScreenWidth / (kolich + addingSize)) + Math.Abs(addingSize);             this.countHeight = (int)Math.Round(ScreenHeight / (kolich + addingSize)) + 5 + Math.Abs(addingSize);              // Создание сетки элементов, в которой будет сыпаться матрица             CreateElement();              // Подсвечиваем кнопку Вкл или Выкл,  зависит от флага             if (this.flagOnOff)             {                 Button_Stop.Background = new SolidColorBrush(Colors.Cyan);                 Button_Start.Background = new SolidColorBrush(Colors.Black);             }             else             {                 Button_Stop.Background = new SolidColorBrush(Colors.Black);                 Button_Start.Background = new SolidColorBrush(Colors.Cyan);             }              // Меняем цвет фона матрицы             ChangeBackground();         }          // Создание сетки элементов, в которой будет сыпаться матрица         public void CreateElement()         {             // Вычисляем тоговый размер шрифта для разметки / переразметки             this.fontSize = kolich + addingFontSize + addingSize;              // Создаем сетку ячеек             for (int i = 0; i < countWidth; i++)             {                 for (int j = 0; j < countHeight; j++)                 {                     // Создаем TextBlock                     TextBlock element = new TextBlock();                      // Задаем имя элемента TextBlock                     element.Name = "TB_" + i + "_" + j;                      // Задаем начальный символ при инициализации сетки ячеек                     // element.Text = char.ConvertFromUtf32(random.Next(0x4E00, 0x4FFF)); // Случайный символ из заданного диапазона                     // element.Text = random.Next(0, 9).ToString(); // Случайным числом                     element.Text = ""; // Пустота                      // Задаем смещение каждого нового элемента TextBlock                     // Также отвечает за разворот вертикальный / горизонтальный                     int turnY = j * (kolich + addingSize);                     int turnX = i * (kolich + addingSize);                      // Включить (false), выключить (true) "поворот экрана"                     if (turnOnOff)                     {                         // Вертикальное, стандартное расположение                         element.Margin = new Thickness(turnX, turnY, 0, 0);                     }                     else                     {                         // Повернутое, горизонтальное расположение                         element.Margin = new Thickness(turnY, turnX, 0, 0);                     }                      // Задаем цвет символа                     element.Foreground = new SolidColorBrush(Colors.Green);                      // Задаем размер шрифта                     element.FontSize = fontSize;                      // Добавляем созданный элемент в Grid                     LayoutRootSecond.Children.Add(element);                 }             }         }          // Событие при нажатии на эелемет Grid (на экран)         private void Event_Grid_Tap_LayoutRoot(object sender, System.Windows.Input.GestureEventArgs e)         {             // Количество одновременно появляющихся змеек после нажатия             for (int i = 0; i < countSimultaneously; i++)             {                 // Останавливаем анимацию                 if (flagOnOff) break;                  Start();                  //Задержка между вызовами. Для красоты матрицы.                 Task.Delay(100);             }         }          // Метод запуска змейки         public async void Start()         {             int count;              // Количество змеек после нажатия на экран в очереди             for (count = 0; count < iteration; count++)             {                 // Начало змейки по горизонтали случайным образом                 int ranX = random.Next(0, countWidth);                  // Начало змейки по вертикали случайным образом                 int ranY = random.Next(-5, countHeight - 1);                  // Длина змейки случайным образом                 int length = random.Next(minLength, maxLength);                  // Скорость смены символов в змейке случайным образом                 int time = random.Next(speedFrom, speedTo);                  await Task.Delay(1);                                  //Обработка змейки                 await RandomElementQ_Async(ranX, ranY, length, time);             }         }          // Определяю элемент, в котором нужно менять символы         public async Task RandomElementQ_Async(int x, int y, int length, int timeOut)         {             // Словарь для хранения идентификаторов ячеек, которые вызывались на предыдущем этапе.             Dictionary<int, TextBlock> dicElem = new Dictionary<int, TextBlock>();              // Задаем цвет символов             Dictionary<string, int> SymbolColor = new Dictionary<string, int>();              // Счетчик, нужен для обработки случаев, когда не выполняется условие if ((y + i) < countHeight && (y + i) >= 0). Смотри на 4 строчки вниз.             // Тоесть элемент в котором нужно менять символы выше или ниже нашей сетки (матрицы элементов).             int count = 0;              // Цикл формирует змейку заданной длины length             for (int i = 0; i <= length; i++)             {                 // Останавливаем анимацию                 if (flagOnOff) break;                  //Проверяем, что б змейка отображалась только в координатах, которые существуют в нашей сетке                 if ((y + i) < countHeight && (y + i) >= 0)                 {                     // Формируем имя элемента, в котором будут меняться символы                     string elementName = "TB_" + x + "_" + (y + i);                      // Получаем элемент по его имени                     object wantedNode = LayoutRoot.FindName(elementName);                     TextBlock element = (TextBlock)wantedNode;                      // Отправляем элемент в словарь, из которого он будет извлекаться для эффекта "падения" и "затухания" змейки                     dicElem[count] = (element);                      // Определяем коеффициент для подсчета яркости. Первый элемент(который падает) -  всега самый яркий, последний - самый темный.                     // Отнимаем 1, потому, что последний элемент (когда к -  максимальное) в итоге получается больше 255 и становится ярким.                     int A_Coefficient = (int)Math.Round((gradientFrom["A"] - 10) / (double)(count + 1)) - 1;                     int R_Coefficient = (int)Math.Round((gradientFrom["R"] - gradientTo["R"]) / (double)(count + 1)) - 1;                     int G_Coefficient = (int)Math.Round((gradientFrom["G"] - gradientTo["G"]) / (double)(count + 1)) - 1;                     int B_Coefficient = (int)Math.Round((gradientFrom["B"] - gradientTo["B"]) / (double)(count + 1)) - 1;                     //int greenCoefficient = (int)Math.Round(255 / (double)(count + 1)) - 1;                      // Вызываем на прорисовку первый, самый яркий падающий элемент. Асинхронно.                     // colorFirstSymbol["A"]. Цвет задается через настройку.                                        await Change(element, timeOut, colorFirstSymbol);                      // Перебираем все  элементы, составляющие змейку на данном этапе. С каждым циклом она увеличивается, пока не достигнет нужной длины.                     for (int k = 0; k <= i; k++)                     {                                                // Останавливаем анимацию                         if (flagOnOff) break;                          // Если змейка начинаеися "выше" начальных координат (например, если y = -5)                         if (dicElem.ContainsKey(k))                         {                             //Извлекаем элементы, которые должны следовать за самым ярким. Создаем эффект "затухания" цвета                             TextBlock previousElement = dicElem[k];                              // Вызываем извлеченные элементы                             // (greenCoefficient * (k + 1)) - 20 Высчитываем яркость так, что б разница между первым и последним была на всех змейках одинаковая                             // и равномерно распределялась независимо от ее длины(количества элементов)                             SymbolColor["A"] = (gradientFrom["A"] - ((i - k) * A_Coefficient));                             SymbolColor["R"] = (gradientFrom["R"] - ((i - k) * R_Coefficient));                             SymbolColor["G"] = (gradientFrom["G"] - ((i - k) * G_Coefficient));                             SymbolColor["B"] = (gradientFrom["B"] - ((i - k) * B_Coefficient));                              Task dsvv = Change(previousElement, timeOut, SymbolColor);                         }                     }                     count++;                 }             }         }          // Метод изменения символов в заданном элеменете         public async Task Change(TextBlock element, int timeOut, Dictionary<string, int> SymbolColor)         {             // Формируем нужный цвет с заданной яркостью             SolidColorBrush NewColor = new SolidColorBrush(new Color()             {                 A = (byte)(SymbolColor["A"]) /*Opacity*/,                 R = (byte)(SymbolColor["R"]) /*Red*/,                 G = (byte)(SymbolColor["G"]) /*Green*/,                 B = (byte)(SymbolColor["B"]) /*Blue*/             });              // При каждом "падении" на 1 клеточку равномерно "затухает"             element.Foreground = NewColor;              // Количество смены символов в каждой ячейке             for (int i = 0; i < countSymbol; i++)             {                 // Останавливаем анимацию                 if (flagOnOff) break;                  // Каждый раз разный символ из заданного диапазона                 element.Text = RandomActualSymbol();                                // Размер шрифта                 element.FontSize = fontSize;                  // Скорость смены символов в ячейке                 await Task.Delay(timeOut);             }         }          // Загрузка данных для элементов ViewModel         protected override void OnNavigatedTo(NavigationEventArgs e)         {             if (!App.ViewModel.IsDataLoaded)             {                 App.ViewModel.LoadData();             }         }          /* ****************************** События ****************************** */         // Настройки. Скорость смены символов.         private void Event_Button_Click_SpeedApplay(object sender, RoutedEventArgs e)         {             // Сохраняем значение их соответствующего TextBox TextBox_SppeedFrom в свойство класса speedFrom             this.speedFrom = int.Parse(TextBox_SppeedFrom.Text.ToString());              // Сохраняем значение их соответствующего TextBox TextBox_SppeedTo в свойство класса speedTo             this.speedTo = int.Parse(TextBox_SppeedTo.Text.ToString());         }          // Настройки. Количество змеек в очереди         private void Event_Button_Click_CountQueue(object sender, RoutedEventArgs e)         {             // Сохраняем значение их соответствующего TextBox TextBox_CountQueue в свойство класса iteration             this.iteration = int.Parse(TextBox_CountQueue.Text.ToString());         }          // Настройки. Количество змеек за нажатие         private void Event_Button_Click_СountSimultaneously(object sender, RoutedEventArgs e)         {             // Сохраняем значение их соответствующего TextBox TextBox_СountSimultaneously в свойство класса countSimultaneously             this.countSimultaneously = int.Parse(TextBox_СountSimultaneously.Text.ToString());         }          // Настройки. Размер шрифта         private void Event_Button_Click_FontSize(object sender, RoutedEventArgs e)         {             // Сохраняем значение их соответствующего TextBox TextBox_FontSize в свойство класса addingFontSize             this.addingFontSize = int.Parse(TextBox_FontSize.Text.ToString());              // Вычисляем тоговый размер шрифта для разметки / переразметки             this.fontSize = kolich + addingFontSize + addingSize;         }          // Настройки. Количество смены символов в ячейке         private void Event_Button_Click_CountSymbol(object sender, RoutedEventArgs e)         {             // Сохраняем значение их соответствующего TextBox TextBox_CountSymbol в свойство класса countSymbol             this.countSymbol = int.Parse(TextBox_CountSymbol.Text.ToString());         }          // Настройки. Выключаем возможность анимирования змеек         private void Event_Button_Click_Stop(object sender, RoutedEventArgs e)         {             this.flagOnOff = true;              // Если flagOnOff в true то подсвечиваем кнопку Stop             if (this.flagOnOff)             {                 Button_Stop.Background = new SolidColorBrush(Colors.Cyan);                 Button_Start.Background = new SolidColorBrush(Colors.Black);             }         }          // Настройки. Включаем возможность анимирования змеек         private void Event_Button_Click_Start(object sender, RoutedEventArgs e)         {             this.flagOnOff = false;              // Если flagOnOff в false то подсвечиваем кнопку Start             if (!this.flagOnOff)             {                 Button_Stop.Background = new SolidColorBrush(Colors.Black);                 Button_Start.Background = new SolidColorBrush(Colors.Cyan);             }         }          // Настройки. Очистка экрана         private void Event_Button_Click_Clear(object sender, RoutedEventArgs e)         {             // Перебираем сетку ячеек и устанавливаем в каждой ячейке как символ - пустоту             for ( int i = 0; i < countWidth; i++)             {                 for (int j = 0; j < countHeight; j++)                 {                     // Формируем имя элемента, который будем очищать                     string elementName = "TB_" + i + "_" + j;                      // Получаем элемент по его имени                     object wantedNode = LayoutRoot.FindName(elementName);                     TextBlock element = (TextBlock)wantedNode;                      // Очищаем значение                     element.Text = "";                 }             }         }          // Настройки. Размер клетки для символа         private void Event_Button_Click_ElementSize(object sender, RoutedEventArgs e)         {             // Сохраняем значение их соответствующего TextBox TextBox_ElementSize в свойство класса addingSize             this.addingSize = int.Parse(TextBox_ElementSize.Text.ToString());              // Количество строк и столбцов. Возвращаем для вертикали             this.countWidth = (int)Math.Round(ScreenWidth / (kolich + addingSize)) + Math.Abs(addingSize);             this.countHeight = (int)Math.Round(ScreenHeight / (kolich + addingSize)) + 5 + Math.Abs(addingSize);              // Останавливаем матрицу             this.flagOnOff = true;              // Удаляем матрицу (сами ячейки)             LayoutRootSecond.Children.Clear();              // Перерисовываем ячейки заново с новыми параметрами             CreateElement();              // Включаем матрицу             this.flagOnOff = false;         }          // Настройки. Задаем максимальную и минимальную длину змейки         private void Event_Button_Click_MaxLength(object sender, RoutedEventArgs e)         {             // Сохраняем значение их соответствующего TextBox TextBox_MinLength в свойство класса minLength             this.minLength = int.Parse(TextBox_MinLength.Text.ToString());              // Сохраняем значение их соответствующего TextBox TextBox_MaxLength в свойство класса maxLength             this.maxLength = int.Parse(TextBox_MaxLength.Text.ToString());         }          // Настройки. Вериткальная / горизонтальная матрица         private void Event_Button_Click_Turn(object sender, RoutedEventArgs e)         {             // Включить (true), выключить (false) "поворот экрана"             if (turnOnOff)             {                 // Сохраняем значение false в свойство класса turnOnOff                 this.turnOnOff = false;                  // Надпись на конопке с именем ToggleButton_Turn меняю на Горизонтально                 ToggleButton_Turn.Content = "Горизонтально";                  // Количество строк и столбцов. Инвертируем для горизонтали.                 this.countHeight = (int)Math.Round(ScreenWidth / (kolich + addingSize)) + 5 + Math.Abs(addingSize);                 this.countWidth = (int)Math.Round(ScreenHeight / (kolich + addingSize)) + 5 + Math.Abs(addingSize);             }             else             {                 // Сохраняем значение true в свойство класса turnOnOff                 this.turnOnOff = true;                  // Надпись на конопке с именем ToggleButton_Turn меняю на Вертикально                 ToggleButton_Turn.Content = "Вертикально";                  // Количество строк и столбцов. Возвращаем для вертикали                 this.countWidth = (int)Math.Round(ScreenWidth / (kolich + addingSize)) + Math.Abs(addingSize);                 this.countHeight = (int)Math.Round(ScreenHeight / (kolich + addingSize)) + 5 + Math.Abs(addingSize);             }              // Останавливаем матрицу             this.flagOnOff = true;              // Удаляем матрицу (сами ячейки)             LayoutRootSecond.Children.Clear();              // Перерисовываем ячейки заново с новыми параметрами             CreateElement();              // Включаем матрицу             this.flagOnOff = false;         }          // Заполняем словарь идентификаторами языка и соответствующие ему ASCII коды символов         public void ListLanguages()         {             // Добавляем в словарь ключь -  название языка и значение -  массив, состоящий из ASCII кодов символов.             languages.Add("Матрица", new int[] { 64, 127 });             languages.Add("Китаский", new int[] { 19968, 20223 });             languages.Add("Английский", new int[] { 64, 127 });             languages.Add("Цифры", new int[] { 48, 57 });             languages.Add("Случайные символы", new int[] { 0, 1000 });             languages.Add("Русский", new int[] { 1040, 1103 });              // Добавляем языки в всплывающую панель для возможности их выбора             foreach (var language in languages)             {                 // Создаю кнопку                 Button newLang = new Button();                  // Задаю надпись кнопки, соответствует языку                 newLang.Content = language.Key.ToString();                  // Горизонтальное выравнивание                 newLang.HorizontalAlignment = HorizontalAlignment.Stretch;                  // Толщина рамки                 newLang.BorderThickness = new Thickness(1);                  // Смещение                 newLang.Margin = new Thickness(0,0,0,0);                  // Событие, при нажатии на кнопку. Одно на все.                 newLang.Click += Event_Button_Click_SelectLanguageUpdate;                  // Добавляю созданую и настроенную кнопку в всплывающее окно                 StackPanel_ButtonDropDownSelectLanguage.Children.Add(newLang);             }         }          // Вызываем эту функцию везде, где нужно показать случайный символ из выбранного языка.         public string RandomActualSymbol()         {             // Получаем массив по ключу, содержащий ASCII коды символов языка, заданного в actualLanguage             int[] sd = (languages[actualLanguage]);              // Выбираем случайнфй символ в диапазоне от первого до последнего символа в заданом языке             return char.ConvertFromUtf32(this.random.Next((int)sd.GetValue(0), (int)sd.GetValue(1)));         }          // Кнопка, в которой показывается текущее выбранное значение языка. при нажатии на нее всплывает меню для выбора другого языка.         private void Event_Button_Click_SelectLanguage(object sender, RoutedEventArgs e)         {             // Показывать (true) / не показывать (false) всплывающее окно (PopUp) при выборе языка             if (flagShowLanguages)             {                 // Показать всплывающее окно                 Popup_ButtonDropDownSelectLanguage.IsOpen = true;                 flagShowLanguages = false;             }             else             {                 // Скрыть всплывающее окно                 Popup_ButtonDropDownSelectLanguage.IsOpen = false;                 flagShowLanguages = true;             }         }          // Всплывающее меню выбора языка.         private void Event_Button_Click_SelectLanguageUpdate(object sender, RoutedEventArgs e)         {             // Если нажата кнопка выбора языка, но другой язык не выбран, то при повторном нажатии меню свернется.             if (!flagShowLanguages)             {                 // Скрыть всплывающее окно                 Popup_ButtonDropDownSelectLanguage.IsOpen = false;                 flagShowLanguages = true;             }              // Получаем название кнопки, которую нажали             string newLanguagr = (sender as Button).Content.ToString();              // Обновляем название кнопки, отображающей выбранный язык             Button_SelectLanguage.Content = newLanguagr;              // Задаем значение языка, в котором выбирать символы случайным образом             this.actualLanguage = newLanguagr;         }          // Меняем цвет фона матрицы         private void Event_Button_Click_ChangeBackground(object sender, RoutedEventArgs e)         {             // Передаем в свойство класса colorMatrixBackground выбранный цвет из элемента ColorPicker для фона матрицы             colorMatrixBackground["A"] = ColorPicker.Color.A;             colorMatrixBackground["R"] = ColorPicker.Color.R;             colorMatrixBackground["G"] = ColorPicker.Color.G;             colorMatrixBackground["B"] = ColorPicker.Color.B;              // Задаем выбранный цвет фона матрицы соответствующей кнопке             Button_BackgroundColor.Background = new SolidColorBrush(new Color()             {                 A = (byte)(colorMatrixBackground["A"]) /*Opacity*/,                 R = (byte)(colorMatrixBackground["R"]) /*Red*/,                 G = (byte)(colorMatrixBackground["G"]) /*Green*/,                 B = (byte)(colorMatrixBackground["B"]) /*Blue*/             });              // Задаем выбранный цвет фона матрицы             ChangeBackground();         }          // Метод изменения цвета фона матрицы. По умолчанию черный.         private void ChangeBackground()         {             // Задаю цвет фона матрицы             LayoutRootSecond.Background = new SolidColorBrush(new Color()             {                 A = (byte)(colorMatrixBackground["A"]) /*Opacity*/,                 R = (byte)(colorMatrixBackground["R"]) /*Red*/,                 G = (byte)(colorMatrixBackground["G"]) /*Green*/,                 B = (byte)(colorMatrixBackground["B"]) /*Blue*/             });         }          // Начальные настройки цветов фона, символов и т.д         private void BeginColorSettings()         {             // Задаем начальный цвет фона матрицы             colorMatrixBackground["A"] = 0;             colorMatrixBackground["R"] = 0;             colorMatrixBackground["G"] = 0;             colorMatrixBackground["B"] = 0;              // Задаем начальный цвет первого символа             colorFirstSymbol["A"] = 255;             colorFirstSymbol["R"] = 248;             colorFirstSymbol["G"] = 248;             colorFirstSymbol["B"] = 255;              // Задаем начальный цвет градиента от (второго символа в змейке)             gradientFrom["A"] = 255;             gradientFrom["R"] = 1;             gradientFrom["G"] = 255;             gradientFrom["B"] = 1;              // Задаем начальный цвет градиента до (последнего символа в змейке)             gradientTo["A"] = 0;             gradientTo["R"] = 0;             gradientTo["G"] = 0;             gradientTo["B"] = 0;         }          // Изменение цвета первого символа         private void Event_Button_Click_FirstSymbolColor(object sender, RoutedEventArgs e)         {             // Передаем в свойство класса colorFirstSymbol выбранный цвет из элемента ColorPicker для фона матрицы             colorFirstSymbol["A"] = ColorPicker.Color.A;             colorFirstSymbol["R"] = ColorPicker.Color.R;             colorFirstSymbol["G"] = ColorPicker.Color.G;             colorFirstSymbol["B"] = ColorPicker.Color.B;              // Задаем выбранный цвет фона матрицы соответствующей кнопке             Button_FirstSymbolColor.Background = new SolidColorBrush(new Color()             {                 A = (byte)(colorFirstSymbol["A"]) /*Opacity*/,                 R = (byte)(colorFirstSymbol["R"]) /*Red*/,                 G = (byte)(colorFirstSymbol["G"]) /*Green*/,                 B = (byte)(colorFirstSymbol["B"]) /*Blue*/             });         }          // Настройки. Задаем градиент змейки. Цвет второго символа.         private void Event_Button_Click_GradientFrom(object sender, RoutedEventArgs e)         {             // Передаем в свойство класса gradientFrom выбранный цвет из элемента ColorPicker для фона матрицы             gradientFrom["A"] = ColorPicker.Color.A;             gradientFrom["R"] = ColorPicker.Color.R;             gradientFrom["G"] = ColorPicker.Color.G;             gradientFrom["B"] = ColorPicker.Color.B;              // Задаем выбранный цвет градиента от змейки соответствующей кнопке             Button_GradientFrom.Background = new SolidColorBrush(new Color()             {                 A = (byte)(gradientFrom["A"]) /*Opacity*/,                 R = (byte)(gradientFrom["R"]) /*Red*/,                 G = (byte)(gradientFrom["G"]) /*Green*/,                 B = (byte)(gradientFrom["B"]) /*Blue*/             });         }          // Настройки. Задаем градиент змейки. Цвет последнего символа.         private void Event_Button_Click_GradientTo (object sender, RoutedEventArgs e)         {             // Передаем в свойство класса gradientTo выбранный цвет из элемента ColorPicker для фона матрицы             gradientTo["A"] = ColorPicker.Color.A;             gradientTo["R"] = ColorPicker.Color.R;             gradientTo["G"] = ColorPicker.Color.G;             gradientTo["B"] = ColorPicker.Color.B;              // Задаем выбранный цвет градиента до змейки соответствующей кнопке             Button_GradientTo.Background = new SolidColorBrush(new Color()             {                 A = (byte)(gradientTo["A"]) /*Opacity*/,                 R = (byte)(gradientTo["R"]) /*Red*/,                 G = (byte)(gradientTo["G"]) /*Green*/,                 B = (byte)(gradientTo["B"]) /*Blue*/             });         }          } } 

Выводы

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

П.С. Если знаете как лучше сделать на данном этапе — прошу в комментарии. И не забывайте, что приложение создается этапами и будут еще как минимум 2 части… Буду благодарен, если подскажете, как решить проблему на последнем видео, так как панорама сдвигается только, если «хватать» за пределами ScrollViewer.

ссылка на оригинал статьи http://habrahabr.ru/post/195760/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *