Введение в Microsoft Silverlight 2

Элементы управления Silverlight: представления и компоновки

Показывать лекцию целиком

Silverlight 2 поставляется с двумя основными сборками, в которых содержатся элементы управления для использования в ваших приложениях. Это core controls ( основные элементы управления) и extended controls ( дополнительные элементы управления).Они являются дополнением к пространству имен System.Windows.Forms, содержащему базовые элементы управления.

В данной лекции будут представлены следующие основные элементы управления и описаны возможности их использования в Silverlight:

  • Button
  • CheckBox
  • HyperlinkButton
  • Image
  • ListBox
  • RadioButton
  • TextBlock
  • TextBox
  • Мы рассмотрим специальные свойства, методы и события, предоставляемые каждым из этих элементов управления, а также свойства, методы и события, общие для всех элементов управления. Изложенная в данной лекции информация не должна быть единственным источником при работе с любым из данных элементов управления, но здесь приводится достаточно базовых сведений, чтобы подтолкнуть вас и помочь начать самостоятельные эксперименты с ними.

    Элемент управления Button

    В Silverlight кнопка реализуется с помощью элемента управления Button. Кнопка реагирует на ввод пользователя с таких устройств ввода, как мышь, клавиатура или стилус, формируя событие Click (Щелчок). Условия формирования кнопкой события Click могут быть настроены несколькими способами. Они задаются свойством ClickMode (Режим щелчка), которое может принимать значения Hover (Наведение), Press (Нажатие) и Release (Отпустить). Эти значения определяют момент формирования события Click. В первом случае, Hover, оно формируется при наведении курсора мыши на кнопку. Во втором случае, Press, оно формируется при нажатии кнопки мыши в момент, когда курсор находится на Button. В третьем случае, Release, это событие возникает, когда пользователь нажал и отпустил кнопку мыши при наведенном на Button курсоре.

    <Canvas x:Name="LayoutRoot" Background="White">
      <Button x:Name="b1" ClickMode="Hover" Content="Button1" 
              Click="ButtonClick">    
      </Button>
      <Button x:Name="b2" Canvas.Top="40" ClickMode="Press" 
              Content="Button2" Click="ButtonClick">    
      </Button>
      <Button x:Name="b3" Canvas.Top="80" ClickMode="Release" 
              Content="Button3" Click="ButtonClick">    
      </Button>
    </Canvas>

    Как видите, для всех этих кнопок определен обработчик события Click и одна и та же функция, ButtonClick, для каждой из них.

    Вот код обработки этого события на языке С#:

    private void ButtonClick(object sender, RoutedEventArgs e) {
    Button b = (Button)sender;
    string strTest = b.Name; }

    Этот код построен по типичному шаблону обработчика события. Он принимает объект отправителя, содержащий ссылку на элемент управления, который сформировал событие (в данном случае, одну из кнопок), и набор аргументов, связанных с этим событием ( RoutedEventArgs ), который включает метаданные о событии.

    Вы заметите, что в данном экземпляре объявлен только один обработчик события. Это делает код аккуратным и понятным. Конечно, вы захотите выяснить, какой из элементов сформировал событие, для этого пригодится отправитель.

    Отправитель - это объект типа Object, поэтому чтобы извлечь из него характерные для кнопок свойства, его просто приводят к типу Button. В данном случае, после приведения этого объекта к типу Button мы можем получить его имя. Если запустить приложение сейчас, можно будет увидеть три кнопки и то, как свойство ClickMode, ассоциированное с каждой из этих кнопок, обусловливает их разное поведение!

    Дополнительным очень полезным свойством является IsEnabled (Активирован). Если ему задано значение false, кнопка отображается на экране, но выглядит неактивной и не формирует события.

    Надпись на кнопке задается свойством Content (Содержимое). В качестве его значения может быть задан простой текст, который будет отображаться как название кнопки. Однако Button также является контейнером, поэтому ее содержимое можно настроить с помощью XAML

    Вот пример кнопки (ужасно некрасивой), содержимое которой описано с помощью XAML:

    <Button x:Name="b1" Click="ButtonClick" Width = "100" Height="100">
      <Canvas>
        <Ellipse Fill= "Green" Width="50" Height="50">      
        </Ellipse>
        <TextBlock Text="Hello"></TextBlock>
      </Canvas>
    </Button>

    Как видите, это обеспечивает чрезвычайную гибкость в представлении кнопок, что позволяет создавать разнообразные кнопки в Веб-приложениях, например, такие как можно увидеть на панели инструментов Microsoft Office 2007.

    Элемент управления CheckBox

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

    При установлении флажка CheckBox формирует событие Checked (Установлен), при снятии флажка формируется событие Unchecked (Снят). Также CheckBox формирует событие Click при каждом щелчке по нему. Аналогично элементу управления Button, CheckBox имеет свойство ClickMode, которому может быть задано значение Hover, Press или Release, определяющее условия формирования события.

    CheckBox может быть флажком с тремя состояниями (поддерживается неопределенное состояние). Это определяется свойством IsThreeState (Три состояния). Если это состояние включено, и пользователь переводит CheckBox в неопределенное состояние, свойству IsChecked присваивается значение null.

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

    Аналогично элементу управления Button, CheckBox является контейнером. Он имеет свойство Content, с помощью которого можно задавать простую строку текста, которая будет отображаться как надпись рядом с флажком, или можно разместить XAML-код в дочернем теге <Content>, для получения более насыщенного эффекта.

    Вот пример каждого из вариантов:

    <StackPanel>
      <CheckBox Checked="CheckBox Checked" Unchecked="CheckBox Unchecked" 
                IsThreeState="True" Content="Test1">     
      </CheckBox>
      <CheckBox Checked="CheckBox Checked" Unchecked="CheckBox Unchecked" 
                IsThreeState="True">
        <CheckBox.Content="" >
          <StackPanel Orientation="Horizontal">
            <TextBlock Text="The Caption"></TextBlock>
            <Image Source="..."/>
          </StackPanel>
        </CheckBox.Content>
      </CheckBox>
    </StackPanel>

    При обработке событий Clicked, Checked и Unchecked, в качестве sender будет выступать объект, который необходимо привести к типу CheckBox, чтобы получить доступ к свойствам флажка.

    Ниже приведен пример:

    private void CheckBox Checked(object sender, RoutedEventArgs e) 
    {
     CheckBox c = (CheckBox)sender;
     bool b = (bool)c.IsChecked; 
    }
    private void CheckBox  Unchecked(object sender, RoutedEventArgs e) 
    {
     CheckBox c = (CheckBox)sender;
     bool b = (bool)c.IsChecked; 
    }

    Элемент управления HyperlinkButton

    HyperlinkButton (Гиперссылка) обеспечивает на странице элемент с возможностью щелчка по нему для перехода по URI, заданному свойством NavigateUri (Uri перехода).

    Например:

    <HyperlinkButton Content="Microsoft"
             NavigateUri="http://www.microsoft.com" />

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

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

    <HyperlinkButton NavigateUri = "http://www.silverlight.net" >
      <HyperlinkButton.Content>
        <Image Source="sl.jpg"/>
      </HyperlinkButton.Content>
    </HyperlinkButton>

    Теперь, когда приложение будет запущено, вы получите изображение, щелчок по которому обеспечит переход по заданному URL

    Свойство TargetName определяет, где будет открываться содержимое, располагающееся по заданному URL Для вывода на экран содержимого URL доступны следующие опции:

  • blank Открывает новое окно браузера без имени.
  • self Замещает текущую HTML-станицу новым содержимым. Если HTML-станица отображается во фрейме, замещается только содержимое рамки.
  • top Замещает текущую HTML-станицу новым содержимым. Даже если HTML-станица отображается во фрейме, меняется содержимое всего окна браузера.
  • parent Замещает всю HTML-станицу.
  • Если используется фреймовая структура, можно задавать имя используемого фрейма.

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

    <Grid x:Name="LayoutRoot" Background="White">
      <HyperlinkButton NavigateUri="http://www.silverlight.net" TargetName="blank" >
        <HyperlinkButton.Content>
          <Image Source="sl.jpg"/>
          </HyperlinkButton.Content>
        </HyperlinkButton>
    </Grid>

    Обратите внимание, что событие Click для HyperlinkButton будет формироваться перед переходом по заданному URI. Это может быть очень полезным, потому что обеспечивает завершение любой предварительной обработки перед загрузкой нового содержимого.

    Далее рассмотрим пример с использованием события Click. Обратите внимание, что NavigateUri задано значение http://www.microsoft.com, но фактически страница переходит по адресу http://www.silverlight.net, потому что Click выполняется раньше перехода и меняет значение NavigateUri.

    Во-первых, рассмотрим XAML:

    <HyperlinkButton NavigateUri="http://www.microsoft.com" 
          TargetName="blank" Click="HyperlinkButtonClick" >
      <HyperlinkButton.Content>
        <Image Source="sl.jpg"/>
      </HyperlinkButton.Content>
    </HyperlinkButton>

    И теперь обратим внимание на выделенный C#-код, в котором обрабатывается событие HyperlinkButtonClick:

    private void HyperlinkButtonClick(object sender, RoutedEventArgs e) 
    { 
     HyperlinkButton h = (HyperlinkButton)sender;
     string strTest = h.NavigateUri.AbsoluteUri;
     if (strTest == "http://www.microsoft.com/") 
     { 
      h.NavigateUri = new Uri("http://www.silverlight.net"); 
     }
    }

    При выполнении этого кода вы увидите, что несмотря на то, что для HyperlinkButton определен один URL, в ходе обработки события Click ему будет задан другой URL, и переход будет выполнен по новому URL

    Элемент управления Image

    Элемент управления Image используется для отображения изображений. Он может принимать форматы файлов .bmp, .jpg и .png. Путь к изображению задается свойством Source. Например:

    <Image Source="sl.jpg" />
    Примечание Если в коде дается ссылка на неподдерживаемый формат, или Source задан несоответствующим образом, будет сформировано событие ImageFailed (Ошибка изображения).

    Если фактические размеры изображения отличаются от заданных для элемента управления Image (т.е. если имеется элемент Image размером 100 * 100 и в него загружается jpg-изображение 2000 * 2000 пикселов), управлять поведением отображения можно с помощью свойства Stretch. Оно может принимать следующие значения:

  • Fill Изменяет размеры изображения соответственно размерам области вывода, используя независимое масштабирование по осям х и у.
  • Uniform Изменяет размеры изображения так, чтобы оно поместилось в элемент управления Image, но при этом сохраняет пропорции изображения.
  • UniformToFill Изменяет размеры изображения так, чтобы оно полностью заполнило область вывода, обрезая его в случае необходимости.
  • None Отображает изображение как есть, что приводит к его обрезке, если оно не помещается в элемент Image.
  • Часто изображение необходимо задать не во время разработки, указывая URI в XAML-коде, а определить его во время выполнения, возможно, как результат обращения к базе данных или чего-либо подобного. В таких случаях в качестве источника для элемента управления Image используется класс BitmapImage (пространства имен System.Windows.Media.Imaging ). Далее приведен пример того, как это делается.

    Сначала XAML:

    <Image x:Name="theImage"/>

    Затем в файле выделенного C# кода необходимо подключить пространство имен:

    using System.Windows.Media.Imaging;

    И вот код, который обеспечит загрузку изображения по URL при загрузке страницы:

    public Page()
    {
     InitializeComponent();
     this.Loaded += new RoutedEventHandler(Page  Loaded); 
    }
    
    void Page  Loaded(object sender, RoutedEventArgs e) 
    {
      Uri uri = new Uri("sl.jpg",UriKind.Relative);
      theImage.Source = new BitmapImage(uri); 
    }

    В данном случае создается новый объект Uri с использованием пути к изображению. Второй параметр в конструкторе - опция, определяющая, как должен вычисляться Uri. Используемый URI может быть относительным (в этом случае поиск заданного ресурса будет вестись в том же каталоге, в котором располагается компонент), абсолютным (в этом случае поиск заданного ресурса будет вестись напрямую, поэтому местоположение должно указываться с применением синтаксиса http://сервер/ресурс) или комбинацией первых двух.

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

    Элемент управления ListBox

    Элемент управления ListBox используется для представления содержимого в виде упорядоченного списка. Это достаточно гибкий элемент управления, так что элементы списка могут создаваться из содержимого любого типа, но обычно список образуется элементами ListBoxItem (Элемент списка), как в следующем примере:

    <ListBox x:Name="theList" SelectionChanged = "ListBoxSelectionChanged"> 
      <ListBoxItem Content="1"/> <ListBoxItem Content="2"/>
      <ListBoxItem Content="3"/> <ListBoxItem Content="4"/> 
      <ListBoxItem Content="5"/> 
    </ListBox>

    Возможность выбора элементов, образующих ListBox, пользователем реализуется посредством события SelectionChanged (Выбранный элемент изменен) и свойства SelectedItem (Выбранный элемент). В предыдущем фрагменте XAML-кода обработкой события SelectionChanged занимался обработчик метода ListBox SelectionChanged. Вот код:

    private void ListBox SelectionChanged(object sender, 
                                    SelectionChangedEventArgs e) 
    {
     ListBoxItem x = theList.SelectedItem as ListBoxItem;
     string strTest = x.Content.ToString(); 
     }

    Обратите внимание, что свойство SelectedItem возвращает object, а не ListBoxItem, потому что (как упоминалось ранее) в ListBox могут размещаться разные типы содержимого. Поэтому, в данном случае, SelectedItem приводится к ListBoxItem.

    Помните, что в ListBox может располагаться разное содержимое. Далее приведен пример, когда ListBox включает составные элементы, образованные компонентами StackPanel, каждый из которых содержит Rectangle, Image и TextBlock.

    <ListBox x:Name="theList" SelectionChanged="ListBox SelectionChanged">
      <StackPanel Orientation = "Horizontal">
        <Rectangle Fill="Black" Height="100" Width="100">      
        </Rectangle>
        <Image Height="100" Width="100" Source="sl.jpg"/>
        <TextBlock Text="Item 1"></TextBlock>
      </StackPanel>
      <StackPanel Orientation = "Horizontal">
        <Rectangle Fill="Black" Height="100" Width="100">      
        </Rectangle>
        <Image Height="100" Width="100" Source="sl.jpg"/>
        <TextBlock Text="Item 2"></TextBlock>
      </StackPanel>
    </ListBox>

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

    (рис 7.1) ListBox со сложными элементами

    Содержимое таких сложных элементов, как представленью здесь, можно получить следующим образом: с помощью SelectedItem получить контейнер (в данном случае, StackPanel ) и затем извлечь из него необходимое содержимое. Например:

    StackPanel s = theList.SelectedItem as StackPanel; 
    TextBlock t = s.Children[2] as TextBlock; 
    string strTest = t.Text;

    Элемент управления RadioButton

    Элемент управления RadioButton, подобно CheckBox используется для фиксирования выбора пользователя. Однако отличается от CheckBox тем, что обычно применяется в ситуациях, когда пользователь должен выбрать единственный вариант из ряда предлагаемых опций.

    Один из способов управления набором опций с возможностью единственного выбора - задать элементы управления RadioButton, соответствующие опциям, как элементы одного уровня в контейнере. Рассмотрим пример:

    <StackPanel Orientation="Vertical" Background="Yellow">
      <RadioButton Content="Option 1" IsChecked= "true">    
      </RadioButton>
      <RadioButton Content="Option 2"></RadioButton>
      <RadioButton Content="Option 3"></RadioButton>
      <RadioButton Content="Option 4"></RadioButton>
      <StackPanel Orientation="Vertical" Background="White">
        <RadioButton Content="Option 5" IsChecked="true">      
        </RadioButton>
        <RadioButton Content="Option 6"></RadioButton>
        <RadioButton Content="Option 7"></RadioButton>
        <RadioButton Content="Option 8"></RadioButton>
      </StackPanel>
    </StackPanel>

    В данном XAML-коде имеется два контейнера StackPanel, один из которых расположен в другом. Первый контейнер содержит опции 1, 2, 3, и 4; второй - опции 5, 6, 7 и 8. В результате, пользователь может выбрать только одну из опций от 1 до 4 и только одну из опций от 5 до 8. Как это работает представлено на рис. 7.2.

    (рис 7.2) Использование элемента управления RadioButton

    Кроме того, опции можно сгруппировать, задавая для каждого RadioButton свойство GroupName (Имя группы). В предыдущем примере в StackPanel располагались опции 1 -4, и Silverlight разрешал пользователю приложения выбирать только одну из них.

    Если потребовалось бы разделить этот набор опций на две группы, чтобы пользователь мог выбирать одну из опций 1 и 2, и одну из опций 3 и 4, вместо контейнера можно было бы использовать группы RadioButton.

    <StackPanel Orientation = "Vertical" Background="Yellow">
      <RadioButton Content="Option 1" IsChecked="true" GroupName="G1" >
      </RadioButton>
      <RadioButton Content="Option 2" GroupName="G1" />
      <RadioButton Content="Option 3" GroupName="G2" />
      <RadioButton Content="Option 4" GroupName="G2" />
      <RadioButton Content="Option 5" GroupName="G3" IsChecked = "true" />
      <RadioButton Content="Option 6" GroupName="G3" />
      <RadioButton Content="Option 7" GroupName="G3" />
      <RadioButton Content="Option 8" GroupName="G3" />
    </StackPanel>

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

    (рис 7.3) Использование элемента управления RadioButton с группами

    Аналогично элементам управления Button и CheckBox, RadioButton имеет свойство ClickMode, определяющее, какое действие пользователя приводит к формированию события Click. Его возможными значениями являются: Hover, при котором событие формируется уже от того, что пользователь проводит курсором по элементу управления; Press, при котором событие формируется по щелчку кнопки мыши по элементу управления; и Release, при котором кнопка мыши должна быть нажата, а потом отпущена, при нахождении курсора мыши на кнопке выбора. Также аналогично элементу управления CheckBox, состояние выбора отдельного RadioButton может быть проверено с помощью свойства IsChecked.

    Элемент управления TextBlock

    Элемент управления TextBlock используется в приложениях Silverlight для отображения текста.

    В самом простом случае, для отображения текст достаточно применить TextBlock с заданным свойством Text. Например:

    <TextBlock Text="1234"></TextBlock>

    Размер текста можно менять, задавая свойство FontSize (в пикселах). Используемый шрифт определяется свойством FontFamily; например, XAML-код для вывода текста шрифтом Arial Black размером 20 выглядел бы так:

    <TextBlock Text="1234" FontFamily="Arial Black" FontSize="20" />

    Свойство FontStyle определяет, как будет выведен текст, курсивом или обычным шрифтом. Чтобы текст отображался курсивом, свойству FontStyle задается значение Italic:

    <TextBlock Text="1234" FontFamily="Arial Black" 
                 FontSize="20" FontStyle="Italic">
    </TextBlock>

    Чтобы использовать обычный шрифт, можно задать свойству FontStyle значение Normal или просто оставить его незаданным.

    Разрывы строк и использование разных шрифтов для отображения текста реализуется с помощью подэлементов TextBlock: <LineBreak> и <Run>. Как следует из его имени, <LineBreak> создает разрывы в тексте с переносом остального текста на новую строку.

    Однако TextBlock не является элементом управления для представления содержимого, как некоторые из элементов управления, которые были представлены в данной лекции ранее. Поэтому если необходимо представить текст иначе, чем все остальное содержимое свойства Text, используется элемент управления Run:

    <TextBlock Width="400" Text="My first text">
      <LineBreak/>
      <Run>My Second Text</Run>
      <LineBreak/>
      <Run>My Third Text</Run>
      <LineBreak/>
      <Run>My Fourth Text</Run>
    </TextBlock>

    Замечательное качество элемента управления Run в том, что он поддерживает те же свойства шрифта, размера, цвета и т.д., что и TextBlock. Таким образом, он предоставляет тот же уровень управления его содержимым, что и TextBlock. Это означает, что текст TextBlock и текст, отображаемый с помощью Run, полностью согласованы.

    Одно из отличий Silverlight 2 от Silverlight 1.0 в том, что TextBlock в Silverlight 2 больше не ограничен девятью шрифтами, встроенными в Silverlight. Silverlight 2 руководствуется правилами замещения системных шрифтов, поэтому если шрифт представлен в системе, текст будет отображен этим шрифтом; если шрифт недоступен в системе, будет использоваться резервный шрифт, определенный операционной системой.

    Итак, рассмотрим пример некоторого XAML, созданного для отображения TextBlock, в котором содержится текст, представленный шрифтом Webdings, а также некоторый текст на китайском языке и иврите:

    <StackPanel Orientation = "Vertical" Background="Yellow">
      <TextBlock Width="400" Text="My first text">
        <LineBreak/>
        <Run FontFamily="Webdings">My Second Text</Run>
        <LineBreak/>
        <Run>китайские иероглифы</Run>
        <LineBreak/>
        <Run>текст на иврите ...</Run>
      </TextBlock>
    </StackPanel>

    Как это выглядит, можно увидеть на рис. 7.4. Данная новая возможность абсолютно упростила разработку Silverlight-приложений с многоязычным пользовательским интерфейсом.

    (рис 7.4) Использование специальных шрифтов в Silverlight

    Элемент управления TextBox

    Элемент управления TextBox обеспечивает пользователям область для ввода текста. В самой простой форме TextBox предоставляет область, в которую пользователь может ввести одну строку текста. Например:

    <StackPanel>
    
      <TextBox /> 
      <TextBox />
    
    </StackPanel>

    Это очень простой StackPanel, содержащий два элемента управления TextBox. На рис. 7.5 показано, как это будет выглядеть. В текстовые поля введены некоторые значения для демонстрации того, как пользователь мог бы заполнять TextBox в приложении.

    (рис 7.5) Простые элементы управления TextBox

    Чтобы эти элементы управления TextBox могли принимать многостроковый ввод, понадобится сделать две вещи. Во-первых, необходимо задать высоту или поместить их в контейнер, обеспечивающий им нестандартную высоту. Затем свойству AcceptsReturn (Допускаются символы возврата каретки) потребуется задать значение True, благодаря чему эти элементы управления смогут принимать символы возврата каретки. Что будет получено в результате, можно увидеть на рис. 7.6.

    (рис 7.6) Элементы управления TextBox настроенные для многострокового ввода текста пользователем.

    Свойство Text такого TextBox будет возвращать объект типа String, в котором каждая строка будет отделена символом \r'.

    Каждый раз при изменении текста в TextBox формируется событие TextChanged (Текст изменен). Заметьте, это происходит после каждого нажатия клавиши, поэтому если необходимо отслеживать все изменения, как одно событие, возможно, лучше будет перехватывать событие LostFocus и работать с текстом из него.

    Элементы управления TextBox автоматически принимают ввод через Редактор метода ввода (Input Method Editor, IME) для поддержки иностранных языков. Если в системе установлена поддержка различных клавиатур и языков , IME будет работать в Silverlight 2 точно также, как для любого другого элемента управления HTML Это можно видеть на рис. 7.7, где в одном TextBox используются разные языки IME - изумительно!

    (рис 7.7) Элемент управления TextBox с текстом на разных языках

    В данном случае, свойство Text возвратит строку с использованием кодировки Unicode со всеми символами и \r в качестве разделителей строк.

    Элементы управления TextBox позволяют выбирать подстроки Text и также обеспечивают возможность настроить то, как выглядит выбранный текст. Для задания или возвращения выбранного в настоящий момент текста используется свойство SelectedText (Выбранный текст). Начало выбранной подстроки можно получить с помощью свойства SelectionStart (Начало выбранной подстроки), ее длину -с помощью свойства SelectionEnd (Конец выбранной подстроки). При любом изменении выбора подстроки формируется событие SelectionChanged (Выбранный элемент изменен). Рассмотрим следующий пример:

    Во-первых, XAML-код:

    <TextBox Height="100" AcceptsReturn="True"
             Text="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
             SelectionChanged="TextBox SelectionChanged">
    </TextBox>

    Здесь определяется событие SelectionChanged, для которого определен обработчик события TextBox SelectionChanged. Рассмотрим:

    private void TextBox SelectionChanged(object sender, RoutedEventArgs e) 
    {
      TextBox t = sender as TextBox;
      int st = t.SelectionStart;
      int ln = t.SelectionLength;
      string strT = t.SelectedText; 
    }

    В данном случае, переменная st типа int содержит индекс начального символа выбранной подстроки (отсчитываемой от нуля), ln -длина выбранной подстроки, и strT- строка, содержащая выбранную подстроку. Итак, например, если выбрана подстрока, как показано на рис. 7.8, st будет равна 9, ln равна 8, и strT будет равна JKLMNOPQ.

    (рис 7.8) Выбор подстроки текста

    Также в TextBox можно использовать разные шрифты, точно так же как это делается в TextBlock. Подробно об этом рассказывалось в разделе "Элемент управления TextBlock" в этой лекции ранее.

    Общие свойства, события и методы

    В предыдущих разделах были подробно рассмотрены базовые элементы управления Silverlight с акцентированием внимания на их особых свойствах, методах и событиях. Однако существует ряд функциональных возможностей, общих для всех или большинства этих элементов управления, и вы должны познакомиться с ними, прежде чем начнете разработку собственных приложений Silverlight.

    Обработка фокуса

    Элементы, которые могут принимать ввод, формируют события GotFocus и LostFocus. Это важное дополнение в Silverlight 2, потому что в Silverlight 1.0 только корневой элемент управления Silverlight мог принимать эти события.

    События GotFocus и LostFocus формируются каждый раз, когда пользователь переходит на или покидает элемент управления, либо наводя курсором мыши, либо используя клавишу Tab. Оба этих события являются событиями, передающимися вверх по иерархии (bubbling events). Это означает, что элемент управления принимает событие, но не обрабатывает его. Событие передается его родителю и так далее вверх по иерархии до тех пор, пока не будет перехвачено обработчиком события.

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

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

  • MouseEnter Это событие формируется при входе курсора мыши в область отображения элемента управления.
  • MouseLeave Это событие формируется, когда курсор мыши покидает область отображения элемента управления.
  • MouseLeftButtonDown Это событие формируется при нажатии пользователем левой кнопки мыши, когда курсор находится над элементом управления.
  • MouseLeftButtonUp Это событие формируется при отпускании удерживаемой левой кнопки мыши, когда курсор находится над элементом управления.
  • MouseMove Это событие формируется при перемещении курсора по элементу управления.
  • Кроме перечисленных событий для обеспечения максимального контроля могут использоваться методы CaptureMouse и ReleaseMouseCapture. Когда для элемента управления вызывается метод CaptureMouse, все события мыши будут направляться в этот элемент управления независимо от того, находится ли курсор мыши в его границах или нет. Метод ReleaseMouseCapture, как следует из его имени, возвращает механизм перехвата событий в нормальное состояние. Эти методы очень полезны для реализации перемещения объектов методом "drag-and-drop". Рассмотрим пример.

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

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

    <UserControl x:Class="MouseEvents.Page" 
         xmlns=" http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xam l" 
         FontFamily="Trebuchet MS" FontSize="11" Width="400" Height="300">
      <Grid x:Name="LayoutRoot" Background = "White">
        <Canvas Width="400" Height="300" Background = "Wheat">
          <Ellipse Canvas.Top="0" Fill="Black" Width = "20" Height="20" 
                   MouseLeftButtonDown="EllipseMouseLeftButtonDown" 
                   MouseLeftButtonUp="EllipseMouseLeftButtonUp" 
                   MouseMove="EllipseMouseMove" />
          <Ellipse Canvas.Top="40" Fill= "Black" Width="20" Height="20" 
                   MouseLeftButtonDown="EllipseMouseLeftButtonDown"
                   MouseLeftButtonUp="EllipseMouseLeftButtonUp"
                   MouseMove="EllipseMouseMove" />
          <Ellipse Canvas.Top="80" Fill= "Black" Width="20" Height="20"
                   MouseLeftButtonDown="EllipseMouseLeftButtonDown"
                   MouseLeftButtonUp="EllipseMouseLeftButtonUp"
                   MouseMove="EllipseMouseMove" />
          <Ellipse Canvas.Top="120" Fill= "Black" Width="20" Height="20"
                   MouseLeftButtonDown="EllipseMouseLeftButtonDown"
                   MouseLeftButtonUp="EllipseMouseLeftButtonUp"
                   MouseMove="EllipseMouseMove" />
        </Canvas>
      </Grid>
    </UserControl>

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

    double beginX = 0; 
    double beginY = 0; 
    bool isMouseDown = false;

    Если курсор находится над любой из кнопок, и нажимается кнопка мыши, выполняется функция EllipseMouseLeftButtonDown.

    private void EllipseMouseLeftButtonDown(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. Оно обрабатывается функцией-обработчиком события EllipseMouseMove:

    private void EllipseMouseMove(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, перехватываемое функцией EllipseMouseLeftButtonUp:

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

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

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

    Кроме событий мыши, существуют события клавиатуры, которые могут формироваться для многих элементов управления. Подробнее об этом рассказывается в следующем разделе.

    (рис 7.9) Приложение, реализующее перемещение объектов методом "Drag and drop"(рис 7.10) Перемещение элементов управления методом "drag and drop"

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

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

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

    Заключение

    В данной лекции были представлены некоторые базовые элементы управления Silverlight ( Button, Check-Box, HyperlinkButton, Image, ListBox, RadioButton, TextBlock и TextBox ) и показано, как они могут использоваться для создания приложений Silverlight. Кроме того, дан обзор свойств, методов и событий, общих для всех элементов управления, что поможет вам начать использовать элементы управления представления и компоновочные элементы управления в Silverlight.

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

    Вернуться к учебному плану