Создание бизнес-приложений с помощью Silverlight - Модальные диалоговые окна в Silverlight

ОГЛАВЛЕНИЕ

Модальные диалоговые окна в Silverlight

Когда представитель центра обработки звонков входит в систему, он получит запрос начать смену, зарегистрировавшись на сервере центра обработки звонков. Процесс регистрации на сервере сохранит сеанс, проиндексированный номером представителя. Этот сеанс будет использован для последующих всплывающих на экране объявлений и других уведомлений. Переход экрана приложения центра вызовов для процесса регистрации показан на рис. 8 и 9. Я буду использовать модельное диалоговое окно, показывающее ход сетевой отправки. Типичные корпоративные бизнес-приложения достаточно свободно используют всплывающие диалоговые окна, модальные и не модальные. Поскольку встроенного элемента диалогового окна DialogBox в Silverlight SDK нет, я покажу, как разработать его Silverlight для использования данном приложении.

До Silverlight не существовало простых способов создания модальных диалогов, поскольку не было простых способов предотвращения передачи событий клавиатуры в интерфейс пользователя. Взаимодействие с мышью можно отключить непрямо, введя UserControl.IsTestVisible = false. Начиная с RC0, параметр Control.IsEnabled = false предотвращает получение любых событий мыши или клавиатуры элементами управления интерфейса пользователя. Я буду использовать System.Windows.Controls.Primitives.Popup для отображения диалогового интерфейса пользователя поверх существующего элемента управления.

Рис. 10 показывает базовый элемент управления SLDialogBox с абстрактными методами GetControlTree, WireHandlers и WireUI. Эти методы будут переопределены дочерними классами, как показано на рис. 11. Primitives.Popup требует экземпляра элемента управления, не являющегося частью дерева управленияЭ, к которому будет присоединен Popup. В коде на рис. 10 метод ShowDialog(true) рекурсивно отключит все дерево управления, так что ни один из содержащихся в нем элементов управления не будет получать событий мыши или клавиатуры. Поскольку мой всплывающий диалог должен быть интерактивным, Popup.Child следует устанавливать из нового экземпляра элемента управления. Реализация GetControlTree в дочерних классах будет действовать как фабрика элементов управления и предоставлять новый экземпляр пользовательского элемента управления, соответствующего требованиям диалога к интерфейсу пользователя.

Рис. 10. Элемент всплывающего диалогового окна DialogBox в Silverlight

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace SilverlightPopups
{
  public abstract class SLDialogBox
  {
  protected Popup _popup = new Popup();
  Control _parent = null;
  protected string _ caption = string.Empty;
  public abstract UIElement GetControlTree();
  public abstract void WireHandlers();
  public abstract void WireUI();

  public SLDialogBox(Control parent, string caption)
  {
  _parent = parent;
  _ caption = caption;
  _popup.Child = GetControlTree();
  WireUI();
  WireHandlers();
  AdjustPostion();

  }
  public void ShowDialog(bool isModal)
  {
  if (_popup.IsOpen)
  return; 
  _popup.IsOpen = true;
  ((UserControl)_parent).IsEnabled = false;
  }
  public void CloseDialog()
  {
  if (!_popup.IsOpen)
  return; 
  _popup.IsOpen = false;
  ((UserControl)_parent).IsEnabled = true;
  }
  private void AdjustPostion()
  {
  UserControl parentUC = _parent as UserControl;
  if (parentUC == null) return; 

  FrameworkElement popupElement = _popup.Child as FrameworkElement;
  if (popupElement == null) return;

  Double left = (parentUC.Width - popupElement.Width) / 2;
  Double top = (parentUC.Height - popupElement.Height) / 2;
  _popup.Margin = new Thickness(left, top, left, top);
  }
  }
}

Рис. 11. NotifyCallPopup.xaml Skin

//XAML Skin for the pop up
<UserControl 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  Width="200" Height="95">
  <Grid x:Name="gridNetworkProgress" Background="White">
  <Border BorderThickness="5" BorderBrush="Black">
  <StackPanel Background="LightGray">
  <StackPanel>
  <TextBlock x:Name="tbCaption" HorizontalAlignment="Center" 
  Margin="5" Text="&lt;Empty Message&gt;" />
  <ProgressBar x:Name="progNetwork" Margin="5" Height="15" 
  IsIndeterminate="True"/>
  </StackPanel>
  <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" >
  <Button x:Name="btAccept" Margin="10,10,10,10"  
  Content="Accept" HorizontalAlignment="Center"/>
  <Button x:Name="btReject" Margin="10,10,10,10"  
  Content="Reject" HorizontalAlignment="Center"/>
  </StackPanel>
  </StackPanel>
  </Border>
  </Grid>
</UserControl>

GetControlTree может быть применен для создания экземпляра пользовательского элемента управления (UserControl) Silverlight, который компилируется в пакет приложения, либо элемент управления может быть создан из файла XAML с помощью XamlReader.LoadControl. Как правило, диалоговые окна можно легко применить в обложках, к которым можно присоединять скомпилированные обработчики во время выполнения. Рис. 11 показывает обложку XAML с кнопками btAccept и btReject. Метод LoadControl выдаст исключение в случае оставления атрибута класса (<userControl class="AdvCallCenter.NotifyCallPopup"…>…</UserControl>) в XAML после завершения задачи разработки в Microsoft Expression Studio или Visual Studio. Все атрибуты обработчика событий интерфейса пользователя должны быть удалены для успешного анализа с помощью LoadControl.

Для создания обложек можно добавить элемент управления Silverlight к проекту, разработать его в Expression и удалить атрибут «класс» и имена обработчика событий, если они есть, присоединенные к элементам управления из файла XAML. Обработчики щелчка могут быть частью дочернего всплывающего класса, как показано на рис. 12, или, как вариант, можно создать отдельную библиотеку обработчиков и соединить ее с элементами управления, используя отражение.

Рис. 12. Реализация NotifyCallPopup

public class NotifyCallPopup : SLDialogBox
{
  public event EventHandler<EventArgs> OnAccept;
  public event EventHandler<EventArgs> OnReject;
  public NotifyCallPopup(Control parent, string msg)
  : base(parent, msg)
  {
  }
  public override UIElement GetControlTree()
  {
  Return SLPackageUtility.GetUIElementFromXaml("NotifyCallPopup.txt");
  }
  public override void WireUI()
  {
  FrameworkElement fe = (FrameworkElement)_popup.Child;
  TextBlock btCaption = fe.FindName("tbCaption") as TextBlock;
  if (btCaption != null)
  btCaption.Text = _caption;
  }
  public override void WireHandlers()
  {
  FrameworkElement fe = (FrameworkElement)_popup.Child;
  Button btAccept = (Button)fe.FindName("btAccept");
  btAccept.Click += new RoutedEventHandler(btAccept_Click);

  Button btReject = (Button)fe.FindName("btReject");
  btReject.Click += new RoutedEventHandler(btReject_Click);
  }

  void btAccept_Click(object sender, RoutedEventArgs e)
  {
  CloseDialog();
  if (OnAccept != null)
  OnAccept(this, null);
  }
  void btReject_Click(object sender, RoutedEventArgs e)
  {
  CloseDialog();
  if (OnReject != null)
  OnReject(this, null);
  }
}

Обработчики могут находиться в любом проекте библиотеки Silverlight, поскольку они будут автоматически скомпилированы в пакет XAP как результат зависимости проекта. Чтобы файлы обложки вошли в пакет XAP, добавьте их к проекту Silverlight как файлы XML и измените расширение на XAML. Действием сборки по умолчанию для файлов с расширением XAML будет компиляция их в DLL приложения. Поскольку я хочу, чтобы эти файлы были упакованы как текстовые файлы, необходимо установить следующие атрибуты из окна свойств:

  • BuildAction = "Content"
  • Copy to Output Directory = "Do Not Copy"
  • Custom Tool = <clear any existing value>

Анализатор XAML (XamlReader.Load) не интересуется расширением; однако использование расширения XAML будет более интуитивно и лучше представлять содержание. SLDialogBox отвечает лишь за показ и закрытие диалога. Дочерние реализации будут модифицированы, чтобы соответствовать нуждам приложения.