Модификация приложения Windows Foundation Presentation



 

Начнём сразу с нового класса. Добавим новый класс в проект. Правая кнопка мыши по названию проекта ( ), затем Добавить -> Создать элемент… (Ctrl+Shift+N). Выбираем (Установленные шаблоны: Visual C #): Класс, вводим Имя: Presenation . cs (пространство имён будет выбрано как у приложения, имя класса будет выбрано по названию файла):

 

Рис. 3. 1. Добавление нового элемента – LWP 09 WPF 02

 

Сформируется новый файл в обозревателе решений ( ), его код такой:

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace LWP09WPF02

{

class Presentation

{

}

}

 

Модифицируем код следующим образом:

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.ComponentModel;

 

namespace LWP09WPF02 // Пространство имён приложения (должно быть такое же как и у главного окна)

{

public class Presentation : INotifyPropertyChanged

{

   private string[] slides = { "01Title.xaml", "02Slide.xaml", "03Slide.xaml" }; // Список слайдов (последовательность определяет вызов)

   private int currentIndex = 0;

   private bool currentTimer = false;

 

   public string[] Slides // Свойство для получения списка всех слайдов

   {

       get { return this.slides; }

   }

 

   public string CurrentSlide // Свойство для получения текущего выбранного слайда

   {

       get { return this.slides[this.currentIndex]; }

   }

 

   public int CurrentIndex // Свойство для получения текущего выбранного индекса для слайда или установки нового индекса и генерации PropertyChanged

   {

       get { return this.currentIndex; }

       set

       {

 

           if (this.currentIndex != value)

           {

               this.currentIndex = value;

               this.OnPropertyChanged("CurrentSlide");

               this.OnPropertyChanged("CanGoBack");

               this.OnPropertyChanged("CanGoNext");

           }

       }

   }

 

   public bool CanGoBack // Логическая переменая (свойство): проверка, есть ли ещё страницы для перехода назад

   {

       get { return this.currentIndex > 0; }

   }

 

   public bool CanGoNext // Логическая переменая (свойство): проверка, есть ли ещё страницы для перехода вперёд

   {

       get { return this.currentIndex < this.slides.Length - 1; }

   }

 

   public void GoBack() // Метод Назад

   {

 

       if (this.CanGoBack)

       {

           this.CurrentIndex--;

       }

   }

 

   public void GoNext() // Метод Вперёд

   {

 

       if (this.CanGoNext)

       {

           this.CurrentIndex++;

       }

   }

 

   public event PropertyChangedEventHandler PropertyChanged; // Событие PropertyChanged

 

   private void OnPropertyChanged(string propertyName) // Метод получения параметра для события PropertyChanged (при изменении свойств компонента), компонент для события: propertyName

   {

 

       if (this.PropertyChanged != null)

       {

           this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

       }

   }

 

   public void GoHome() // Метод Домой

   {

       this.CurrentIndex = 0;

   }

 

   public bool GoAuto // Метод Авто

   {

       get { return this.currentTimer; }

       set

       {

 

           if (this.currentTimer == true)

           {

               this.currentTimer = false;

           }

           else

           {

               this.currentTimer = true;

           }

       }

   }

}

}

 

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

 

Все слайды, добавляемые в студии автоматически или в ручную должны быть типа Page (страница), а не Window. Page, как уже было показано в предыдущей лабораторной работе прекрасно подходит для веб-браузера и отображает всё содержимое.

 

Добавим три слайда (потом ещё один, четвёртый в Expression Blend). Для этого нам нужно выбрать в окне добавления нового элемента (Установленные шаблоны -> WPF) выберем элемент Страница ( WPF ). Для первой страницы Имя укажем как 01 Title.xaml:

 

Рис. 3. 2. Добавление новой страницы: Страница ( WPF ), тип Page

 

XAML-код для 01 Title . xaml:

 

<Page x:Class="LWP09WPF02._01Title"

 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

 mc:Ignorable="d"

 d:DesignHeight="300" d:DesignWidth="300"

  Title="_01Title">

 

<Grid>

       

</Grid>

</Page>

 

Добавим ещё две такие же страницы под именами 02 Slide . xaml и 03 Slide . xaml.

 

Код добавленных страниц трогать мы не будем (это просто не нужно). Всё будет выполнять главное окно и наш класс. Поэтом добавление новых страниц слайда максимально упрощено и превращается в работу по заполнению их содержимым (как в PowerPoint). Естественно, чтобы добавить для страницы уникальную функциональность, код придётся редактировать. Но лучше всю функциональность организовывать в уже готовом классе, тогда будет максимально просто добавлять новые функции для новых слайдов не заботясь о правильном перенесении кода. Для слайдов же останется лишь добавлять обработчики новых методов и расставлять новые элементы с привязкой.

 

Изменим код главного окна следующим образом:

 

<Window x:Class="LWP09WPF02.MainWindow"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:LWP09WPF02="clr-namespace:LWP09WPF02"

   Title="Презентация WPF (C#)" Height="600" ResizeMode="NoResize" WindowState="Maximized" WindowStyle="None" Name="Window" KeyDown="Window_KeyDown" PreviewMouseMove="Window_PreviewMouseMove" PreviewMouseLeftButtonDown="Window_PreviewMouseLeftButtonDown">

<Window.Resources>

   <LWP09WPF02:Presentation x:Key="presentation"/>

</Window.Resources>

 

<Grid>

   <Viewbox Margin="10,20,10,40" Stretch="Uniform">

       <StackPanel>

           <!-- Подставляем всегда: заголовок страницы -->

           <TextBlock VerticalAlignment="Top" Height="84" FontFamily="Calibri" FontSize="65" FontWeight="Bold" Text="{Binding Content.Title, ElementName=Frame, Mode=Default}" TextAlignment="Center" TextWrapping="Wrap">

           </TextBlock>

           <!-- Подставляем всегда: содержимое слайда -->

           <Frame Height="600" Source="{Binding CurrentSlide, Source={StaticResource presentation}}" x:Name="Frame" NavigationUIVisibility="Hidden" Background="{x:Null}" Focusable="False"/>

       </StackPanel>

   </Viewbox>

 

   <Button Height="36.709" Content="Назад" Click="Back_Click" RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Left" Margin="10,0,0,10" VerticalAlignment="Bottom" IsEnabled="{Binding CanGoBack, Source={StaticResource presentation}}" />

   <Button HorizontalAlignment="Right" Margin="0,0,10,10" VerticalAlignment="Bottom" Height="36.709" Content="Вперёд" Click="Next_Click" IsEnabled="{Binding CanGoNext, Source={StaticResource presentation}}" />

   <Button Content="Домой" Height="36.709" Margin="80,0,0,10" VerticalAlignment="Bottom" Click="Home_Click" HorizontalAlignment="Left" />

   <Button Content="Авто" Height="36.709" HorizontalAlignment="Right" Margin="0,0,80,10" VerticalAlignment="Bottom" Click="Auto_Click" />

   <Ellipse Height="23" HorizontalAlignment="Right" Margin="0,0,150,12" Name="EAuto" Stroke="Black" VerticalAlignment="Bottom" Visibility="Hidden" />

   <Label Content="А" Height="26" HorizontalAlignment="Right" Margin="0,0,150,12" Name="LAuto" VerticalAlignment="Bottom" Visibility="Hidden" />

</Grid>

</Window>

 

На самом деле это было сконструрировано в местном визуальном редакторе. Сначала были изменены свойства главного окна:

Tilte: Презентация WPF (C#)
Height: 600
Width: 800
ResizeMode: NoResize
WindowState: Maximized
WindowStyle: None

 

Затем добавили ресуры окна:

 

   <LWP09WPF02:Presentation x:Key="presentation"/>

 

Добавили элемент ViewBox ( ), растянув его по сетке и закрепив, дав свойство:

Stretch: Uniform

 

Затем внутрь ViewBox запихнули StackPanel с двумя элементами: TextBox и Frame ( ). Ключевые привязки для отображения подгружаемого содержимого для этих элементов такие:

 

TextBox:

Text="{Binding Content.Title, ElementName=Frame, Mode=Default}"

 

Frame:

Source="{Binding CurrentSlide, Source={StaticResource presentation}}"

 

Поставили кнопки Button (4 штуки), а также нарисовали маленький эллипс и внутрь поставили Label с надписью «А». Кнопки, эллипс и надпись были поставлены вне элемента ViewBox, так как они должны отображаться на каждом слайде.

 

Ключевые привязки (если включена) на события: для кнопки Назад:

IsEnabled="{Binding CanGoBack, Source={StaticResource presentation}}"

 

Кнопка Вперёд:

IsEnabled="{Binding CanGoNext, Source={StaticResource presentation}}"

 

Модифицируем код самого главного (MainWindow . xaml) окна следующим образом: для начала задаём окну имя Window:

 

Добавим новые пространства имён в начало файла MainWindow . xaml . cs:

 

using System.IO; // Для работы с классом File

using System.Windows.Threading; // Для создания таймеров

 

Объявим новые переменные после объявления классаокна:

 

public partial class MainWindow : Window

{

   private Presentation NewPresentation; // Создаём экземпляр нашего класса Presenation

   private DispatcherTimer Timer1;

   private DispatcherTimer Timer2;

   private bool AutoClick;

 

Изменим код метода MainWindow():

 

   public MainWindow()

   {

       InitializeComponent();

       NewPresentation = (Presentation)this.FindResource("presentation");

       AutoClick = false;

 

       // После перезапуска приложения, стартует слайд, дата изменения которого наиболее поздняя (дата изменения страницы XAML)

       int IndexLastWritten = 0;

       DateTime latestDateTimeWritten = DateTime.MinValue;

 

       for (int i = 0; i < NewPresentation.Slides.Length; i++) // Проходим по общему числу слайдов (через наш собственный класс и метод)

       {

           String Slide = NewPresentation.Slides[i];

           DateTime DateLastWritten = File.GetLastWriteTime(@"..\..\" + Slide); // Узнаём дату из каталога проекта по файлам слайдов

 

           if (DateLastWritten.CompareTo(latestDateTimeWritten) > 0)

           {

               latestDateTimeWritten = DateLastWritten;

               IndexLastWritten = i;

           }

       }

       NewPresentation.CurrentIndex = IndexLastWritten;

       //presentation.CurrentIndex = 0; // Если нам нужно, можем всегда стартовать с первой страницы

 

       // Создаём таймеры, которые обрабатывают исчезновение мышки после 5 секунд и перелистывание слайда через 15 секунд

       Timer1 = new DispatcherTimer();

       Timer1.Interval = TimeSpan.FromSeconds(5);

       Timer1.Tick += new EventHandler(Timer1_Tick);

       Timer1.Start();

 

       Timer2 = new DispatcherTimer();

         Timer2.Interval = TimeSpan.FromSeconds(15);

       Timer2.Tick += new EventHandler(Timer2_Tick);  

   }

 

Впишем события для таймеров. Первый таймер Timer 1 скрывает курсор по событию Tick, а второй Timer 2 вызывает из класса Presentation метод GoNext ():

 

   private void Timer1_Tick(object sender, EventArgs e)

   {

       this.Cursor = Cursors.None; // Убираем курсор мышки

   }

 

   private void Timer2_Tick(object sender, EventArgs e)

   {

       NewPresentation.GoNext();

   }

 

Метод для показа курсора мышки ShowCursor () после того, как её скрыли (вызов метода находится в ином месте: в методе нажатия левой клавиши мышки). После вызова, снова запускает Timer 1 отвечающий за событие скрытия курсора.

 

   private void ShowCursor()

   {

       Timer1.Start();

       this.ClearValue(FrameworkElement.CursorProperty);

   }

 

Теперь определим события окна Window. Первым станет событие PrieviewMouseLeftButtonDown отвечающее за нажатие левой кнопки мышки в окне формы:

 

   private void Window_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)

   {

       ShowCursor();

       Point CurrentPoint = e.GetPosition(this);

       TranslateTransform Transform = new TranslateTransform(CurrentPoint.X, CurrentPoint.Y);

       //this.ClickCanvas.RenderTransform = Transform;

   }

 

Закомментированная строчка относится к ещё не определённой нами функциональности (а именно к анимации «нажатия», о которой ниже). Пока что поясним, почему выбрана группа методов PreviewMouse … вместо обычных методов Mouse …. Разница в уровне восприятия события. В первом события MouseLeftButtonDown отслеживаются нажатия только в самой форме, если же нажатие было совершено в каком-либо элемента, событие не возникнет.

 

Событие PreviewMouseMove формы:

 

   private void Window_PreviewMouseMove(object sender, MouseEventArgs e)

   {

       ShowCursor();

   }

 

События Click всех кнопок:

 

  private void Back_Click(object sender, RoutedEventArgs e)

   {

       NewPresentation.GoBack();

   }

 

   private void Next_Click(object sender, RoutedEventArgs e)

   {

       NewPresentation.GoNext();

   }

 

   private void Home_Click(object sender, RoutedEventArgs e)

   {

       NewPresentation.GoHome();

   }

 

   private void Auto_Click(object sender, RoutedEventArgs e)

   {

 

       if (AutoClick == false)

       {

           AutoClick = true;

           NewPresentation.GoAuto = true;

           Timer2.Start();

       }

       else

       {

           AutoClick = false;

           NewPresentation.GoAuto = false;

           Timer2.Stop();

       }

 

       if (!NewPresentation.GoAuto)

       {

           LAuto.Visibility = Visibility.Hidden;

           EAuto.Visibility = Visibility.Hidden;

       }

       else

       {

           LAuto.Visibility = Visibility.Visible;

           EAuto.Visibility = Visibility.Visible;

       }

   }

 

Кнопки Назад, Домой и Вперёд вызывают методы класса Presentation и работают просто. Если есть слайд до текущего слайда, Назад отображается активной и её можно нажать, будет выбран предыдущий слайд из списка, определяющего порядок показа. Если нажата кнопка Домой, происходит вызов самого первого слайда. Нажатие кнопки Вперёд (если активна), переводит отображение на следующий слайд.

Работа кнопки Авто заключается в следующем: проверяем состояние (была нажата или нет). Если нажата, передаём параметр нажатия в класс Presentation, активируем таймер или останавливаем, и затем показываем или скрываем элементы на главной формы, отображающие состояние нажатия кнопки (эллипс и текст «А»). Передачу параметра в свойство можно и не делать. Но лучше всё-таки передавать ключевые параметры формы чтобы можно было получить их в любом месте приложения.

 

Событие KeyDown (нажатие клавиши) окна формы. Ловим нажатия клваш стрелок (лево, право) и Esc:

 

   private void Window_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)

   {

       if (e.Key == Key.Left)

       {

           NewPresentation.GoBack();

           e.Handled = true;

       }

       else if (e.Key == Key.Right)

       {

           NewPresentation.GoNext();

           e.Handled = true;

       }

       else if (e.Key == Key.Escape)

       {

           Application.Current.Shutdown();

           e.Handled = true;

        }

   }

 

Рис. 3. 3. Модифицированная форма приложения

 

Компилируем, проверяем работоспособность. Попробуем изменить какой-либо слайд и добавить на него элементов, а также изменить свойство Title для слайда (не забываем что открывается тот слайд, который мы редактировали последним, полезно когда в данный момент нам нужно посмотреть как выглядит слайд «в живую»; если не хотим такую функциональность, выключаем как написано в комментариях к коду)

 


Дата добавления: 2019-09-13; просмотров: 194; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!