Создание бизнес-приложений с помощью 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="<Empty Message>" />
<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 отвечает лишь за показ и закрытие диалога. Дочерние реализации будут модифицированы, чтобы соответствовать нуждам приложения.