Опубликован: 01.03.2010 | Уровень: специалист | Доступ: платный
Лекция 7:

Дизайн и разработка приложений Silverlight в Visual Studio 2008

Обработка событий мыши

Элементы управления Silverlight формируют несколько событий мыши:

  • MouseEnter Событие MouseEnter формируется при входе курсора мыши в область отображения элемента управления.
  • MouseLeave Событие MouseLeave формируется, когда курсор мыши покидает область отображения элемента управления.
  • MouseLeftButtonDown Событие MouseLeftButtonDown формируется при нажатии пользователем левой кнопки мыши, когда курсор находится над элементом управления.
  • MouseLeftButtonUp Событие MouseLeftButtonUp формируется при отпускании удерживаемой левой кнопки мыши, когда курсор находится над элементом управления.
  • MouseMove Событие MouseMove формируется при перемещении курсора по элементу управления.

Кроме перечисленных событий для обеспечения максимального контроля могут использоваться методы CaptureMouse и ReleaseMouseCapture. Когда для элемента управления вызывается метод CaptureMouse, все события мыши направляются в этот элемент управления независимо от того, находится ли курсор мыши в его границах или нет. Метод ReleaseMouseCapture, как следует из его имени, возвращает механизм перехвата событий в нормальное состояние. Эти методы очень полезны для реализации перемещения объектов методом "drag-and-drop". Далее представлен пример использования этих событий и методов.

Использование событий мыши для реализации перемещения объектов методом "Drag-and-drop"

Ниже представлен XAML-документ, обеспечивающий прорисовку эллипсов на странице. Обратите внимание, что для всех эллипсов определены одни и те же обработчики событий мыши:

<Canvas Width="640" Height="480" Background="Wheat">
  <Ellipse 
      Canvas.Top="0" 
      Fill="Black" 
      Width="20" 
      Height="20" 
      MouseLeftButtonDown="Ellipse_MouseLeftButtonDown" 
      MouseLeftButtonUp="Ellipse_MouseLeftButtonUp" 
      MouseMove="Ellipse_MouseMove" />
  <Ellipse 
      Canvas.Top="40" 
      Fill="Black" 
      Width="20" Height="20" 
      MouseLeftButtonDown="Ellipse_MouseLeftButtonDown" 
      MouseLeftButtonUp="Ellipse_MouseLeftButtonUp" 
      MouseMove="Ellipse_MouseMove" />
  <Ellipse 
      Canvas.Top="80" 
      Fill="Black" 
      Width="20" Height="20" 
      MouseLeftButtonDown="Ellipse_MouseLeftButtonDown" 
      MouseLeftButtonUp="Ellipse_MouseLeftButtonUp" 
      MouseMove="Ellipse_MouseMove" />
  <Ellipse 
      Canvas.Top="120" 
      Fill="Black" Width="20" 
      Height="20" 
      MouseLeftButtonDown="Ellipse_MouseLeftButtonDown" 
      MouseLeftButtonUp="Ellipse_MouseLeftButtonUp" 
      MouseMove="Ellipse_MouseMove" />
</Canvas>

Теперь рассмотрим выделенный код. Во-первых, нам необходимы переменные для сохранения х и у координат курсора мыши в момент начала перемещения методом "drag-and-drop" и еще одна переменная для обозначения того, удерживается ли кнопка мыши в настоящий момент. Если курсор находится над любой из кнопок, и нажимается кнопка мыши, выполняется функция Ellipse_MouseLeftButtonDown.

double beginX = 0; 
double beginY = 0; 
bool isMouseDown = false;
private void Ellipse_MouseLeftButtonDown(object sender,  MouseButtonEventArgs e)
{
  Ellipse b = sender as Ellipse; 
  beginX = e.GetPosition(this).X; 
  beginY = e.GetPosition(this).Y; 
  isMouseDown = true; b.CaptureMouse();
}

Отправителем является универсальный объект, поэтому, прежде всего, необходимо привести его к типу эллипс. После этого используем аргумент MouseButtonEventArgs (Аргументы событий кнопки мыши) для получения текущих координат х и у и задания их как начальных значений. Затем, поскольку кнопка мыши удерживается нажатой, ее перемещения должны отслеживаться, поэтому переменной isMouseDown задается значение True. Наконец, мы хотим отслеживать события мыши для этого эллипса (любого из заданных) таким образом, чтобы даже если пользователь уводит курсор мыши с этого эллипса, он продолжал получать события.

Итак, поскольку пользователь двигает мышью, должно формироваться событие MouseMove. Оно обрабатывается функцией-обработчиком события Ellipse_MouseMove:

private void Ellipse_MouseMove(object sender, MouseEventArgs e)
{
  if (isMouseDown) 
  { 
    Ellipse b = sender as Ellipse; 
    double currX = e.GetPosition(this).X; 
    double currY = e.GetPosition(this).Y; 
    b.SetValue(Canvas.LeftProperty, currX); 
    b.SetValue(Canvas.TopProperty, currY); 
  }
}

Это событие формируется при прохождении курсора мыши по эллипсу, независимо от того, выполняется ли перемещение этого эллипса или нет. Но нас интересуют только варианты, когда пользователи перетягивает эллипс, а это, по определению, означает, что переменная isMouseDown имеет значение True. В этом случае мы получаем текущие координаты курсора мыши и используем их для задания присоединенных свойств Top и Left эллипса. В результате будет создан эффект перетягивания эллипса соответственно координатам курсора мыши.

Наконец, при отпускании удерживаемой кнопки мыши формируется событие MouseLeftButtonUp, перехватываемое функцией Ellipse_MouseLeftButtonUp:

private void Ellipse_MouseLeftButtonUp(object sender,
  MouseButtonEventArgs e) 
{ 
  Ellipse b = sender as Ellipse; 
  isMouseDown = false; 
  b.ReleaseMouseCapture(); 
}

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

Пример использования событий мыши для реализации перемещения объектов методом "Drag-and-drop"

Рис. 7.14. Пример использования событий мыши для реализации перемещения объектов методом "Drag-and-drop"

На рисунке показано, как приложение выглядит в исходном состоянии. Если пользователь наведет курсор мыши на любой из эллипсов и затем нажмет кнопку мыши и продолжит перемещение, эллипс начнет двигаться за курсором. Таким образом, пользователь может менять расположение эллипсов на экране методом "drag-and-drop".

Использование клавиатуры

Кроме элемента управления TextBox, который предлагает пользователю возможность ввода текста с клавиатуры, многие элементы управления формируют события KeyDown и KeyUp, которые могут использоваться для перехвата ввода с клавиатуры. Событие KeyDown формируется при каждом нажатии клавиши, когда фокус находится на элементе. Функция-обработчик этого события принимает универсальный объект-отправитель и объект KeyEventArgs, который может использоваться для извлечения информации о нажатой клавише. Он имеет свойство key, возвращающее объект Key с информацией о клавише. Это платформонезависимое свойство, поэтому оно лучше всего подходит для использования в приложениях Silverlight. KeyEventArgs предлагает также еще одно свойство, PlatformKeyCode (Код клавиши на данной платформе), которое может использоваться со свойством key для получения кодов клавиш, используемых в конкретной операционной системе.

Кроме того, статическое свойство Keyboard.Modifers возвращает значение ModifierKeys (Модифицирующие клавиши), которое может использоваться для определения того, какая из модифицирующих клавиш (Alt, Ctrl, Shift, Windows) была нажата. Просто используйте побитовое И на возвращенное значение свойства для проверки искомой модифицирующей клавиши (например, Shift).

Стили

Стиль создается в разделе <Resources> (Ресурсы) контейнера. Здесь может быть создан один или более стилей, для которых задается имя стиля и тип объекта, к которому будет применяться стиль. Например, чтобы создать стиль TextBlockStyle (Стиль текстового блока) для элемента управления TextBlock, используется такой XAML:

<UserControl.Resources>
  <Style TargetType="TextBlock" x:Key="TextBlockStyle">
    <Setter Property="FontFamily" Value="Comic Sans Ms"></Setter>
    <Setter Property="Foreground" Value="MediumBlue"></Setter>
    <Setter Property="FontSize" Value="30"></Setter>
  </Style>
</UserControl.Resources>

Для стиля задается тип элемента управления, к которому он может применяться. Однако то, что этот стиль предполагается для TextBlock, не означает, что все экземпляры TextBlock будут использовать его. Вы не ограничены одним стилем для одного типа. В стиле должен быть задан тип элемента управления, для которого предназначен стиль, а также может быть задан Key (Ключ) стиля. Таким образом, можно иметь множество разных описаний стилей для элемента управления TextBlock с разными Key. Тогда, задавая свойство Style (Стиль) для разных TextBlock, вы просто выбираете тот стиль, который желаете применить к тому или иному TextBlock, по имени. Это будет продемонстрировано через мгновение, но сначала рассмотрим настройку стиля свойств TextBlock. Для этого используется Setter (Установщик). Setter - это тег XAML, определяющий свойство и значение, которое необходимо задать этому свойству.

Этот стиль должен быть определен на странице как ресурс. Как видите, корневым элементом XAML на странице является UserControl. У него есть дочерний элемент <UserControl.Resources>. Тег <Style> помещается в него.

Применяется этот стиль к TextBlock посредством свойства Style. Поскольку стиль определен как ресурс, для задания имени стиля используется синтаксис с ключевым словом StaticResource (Статический ресурс):

<TextBlock 
    Text="Click!" 
    Style="{StaticResource TextBlockStyle}"/>

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

В данном случае действие стиля ограничено рамками одного пользовательского элемента управления UserControl. Чтобы расширить стиль на все страницы приложения, необходимо поместить стиль в контейнер <Application.Resources> файла App.xaml.

<Application.Resources>
  <Style TargetType="TextBlock" x:Key="TextBlockStyle">
    <Setter Property="FontFamily" Value="Arial"></Setter>
    <Setter Property="Foreground" Value="MediumBlue"></Setter>
    <Setter Property="FontSize" Value="30"></Setter>
  </Style>
</Application.Resources>

Шаблоны

В Silverlight можно определить стиль сразу всего элемента управления, включающего несколько других элементов, например, Button и образующих его элементов управления, т.е. StackPanel, Image и TextBlock.

Шаблоны действуют абсолютно аналогично стилям: размещаются в разделе <Resources> и описываются с помощью тега Setter. Чтобы создать Template (Шаблон), задается свойство Template и затем с помощью <Setter.Value> определяется ControlTemplate для заданного элемента управления:

<UserControl.Resources>
  <Style TargetType="TextBlock" x:Key="TextBlockStyle">
    <Setter Property="FontFamily" Value="Comic Sans Ms"></Setter>
    <Setter Property="Text" Value="Click!"></Setter>
    <Setter Property="Foreground" Value="MediumBlue"></Setter>
    <Setter Property="FontSize" Value="15"></Setter>
  </Style>
  <Style x:Key="ImageButton" TargetType="Button">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="Button">
          <Button>
            <Button.Content>
              <StackPanel Orientation="Vertical">
                <Image 
                    Source="1.jpg" 
                    Height="48" Width="48">                                        
                </Image>
                <TextBlock 
                 Style="{StaticResource TextBlockStyle}">                                        
                </TextBlock>
              </StackPanel>
            </Button.Content>
          </Button>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>        
</UserControl.Resources>
<Button Style="{StaticResource ImageButton}"/>
<Button Content="Button2"/>

В результате получится кнопка, как показано на рис. 7.15

Применение шаблона и стиля к элементу управления Button

Рис. 7.15. Применение шаблона и стиля к элементу управления Button

Заключение

В данном разделе изучен некоторый базовый набор элементов управления Silverlight. Всего элементов управления после установки Silverlight SDK и Toolkit - 79. Так же показан способ применения шаблонов и стилей к элементам управления. Они позволяют унифицировать и настраивать внешний вид и поведение всех создаваемых вами элементов управления во всем приложении Silverlight.

Иван Циферблат
Иван Циферблат
Россия, Таганрог, 36, 2000