9 Мая 2009 года.
Здравствуйте, уважаемые сильверлайтеры! Вот и прошёл месяц, и мы, рады представить Вам второй выпуск нашего бюллетеня. Как всегда ждём от Вас откликов, мнений и предложений по улучшению бюллетеня и сайта silverlighter.ru в целом!
И, так как, сегодня 9 мая, не могу не поздравить Вас с днём Великой Победы!
Доступна электронная книга "Первый взгляд Silverlight 3" на русском языке. Вышел Moonlight 2.0 preview 1. Для ознакомления и тестирования стал доступен Moonlight 2.0 preview 1. Напомню, что это open-source реализация технологии Silverlight под множество платформ.
Intuit.ru опубликовал курс "Введение в Microsoft Silverlight 2". Всем начинающим сильверлайтерам будет полезно - Этот курс может стать вашим первым взгляд на инструменты и технологии создания приложений с использованием Silverlight 2.
DeepZoomPix: хостинг ваших фотографий в DeepZoom-виде. Открыт онлайн-сервис по хранению и просмотру фотографий на базе DeepZoom. Сервис будет доступен до 31.12.2009, так что спешите оценить.
Webby Awards использует Silverlight. Крупнейшая в мире интернет-премия Webby Awards в этом году выбрала технологию Silverlight для предоставления контента на своем сайте.
У New York Times появился Silverlight Kit. Совсем недавно был анонсирован Silverlight Kit для New York Times APIs.
Многие улучшения третьего Сильверлайта направлены, в том числе и на упрощение создания бизнес приложений. Теперь нам доступны .NET RIA Services, а также расширен набор элементов управления для работы с данными. Одним из новых элементов управления является DataForm. О нём мы сегодня и поговорим. Элемент управления DataForm позволяет делать практически всё тоже, что и DataGrid, только в отличие от последнего, DataForm нацелен на работу с одной записью данных, а не с набором. Хотя и позволяет производить навигацию по набору данных, добавлять, удалять, просматривать и редактировать записи. При этом в каждый момент времени отображается только одна запись данных. В данной статье речь пойдёт о том, как работать с формами данных (DataForm). Рассказывается, как в графическом интерфейсе Сильверлайт приложений отобразить произвольную бизнес сущность, настроить валидацию отдельных полей и всей формы в целом, а также освещаются и другие не менее интересные темы, связанные с формами данных.
Введение.
Итак, давайте в Visual Studio 2008 создадим новый проект Silverlight приложения. Если Вы не знаете, как это сделать, обратитесь к соответствующим статьям и скринкастам на нашем сайте.
Приложение назовём «DataFormTest». И добавим в раздел References проекта сборку «System.Windows.Controls.Data.DataForm». Она может быть добавлена и автоматически при перетаскивании DataForm из Tolbox в XAML код, но сейчас мы всё сделаем вручную. Перейдём к XAML коду страницы MainPage.xaml и свяжем XML и CLR пространства имён. Это нужно для того, чтобы мы могли видеть из XAML .NET объекты. Для этого добавим код:
xmlns:dataControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm"
в элемент UserControl. Теперь он будет выглядеть приблизительно следующим образом:
<UserControl xmlns:dataControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm"
x:Class="DataFormTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
MinWidth="400" MinHeight="300">
...
</UserControl>
* This source code was highlighted with Source Code Highlighter.
Теперь пришло время добавить на страницу форму данных.
<dataControls:DataForm x:Name="mainData" Margin="50"></dataControls:DataForm>
* This source code was highlighted with Source Code Highlighter.
Мы также задали для формы данных имя «mainData».Если запустить приложение, то мы увидим базовый интерфейс формы, но так как самих данных нет, особого интереса он не представляет.
Давайте добавим в проект DataFormTest новый класс «Person», который будет представлять собой данные о человеке. Для этого щёлкнем правой кнопкой мыши по проекту в окне Solution Explorer и выберем «Add->Class...». В появившемся диалоговом окне зададим имя класса и щёлкнем на кнопку OK. Теперь добавим в созданный нами класс свойства, нужные для хранения информации о человеке. А именно нас интересуют имя, фамилия и дата рождения. Вот полный исходный код данного класса:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
}
* This source code was highlighted with Source Code Highlighter.
Теперь в C# коде страницы MainPage.xaml создадим новый объект класса Person и установим этот объект текущим элементом данных для ранее созданной формы данных.
public MainPage()
{
InitializeComponent();
Person ivan = new Person();
ivan.FirstName = "Иван";
ivan.LastName = "Петров";
ivan.DateOfBirth=new DateTime(1980,1,1);
mainData.CurrentItem = ivan;
}
* This source code was highlighted with Source Code Highlighter.
Если теперь запустить приложение, то мы увидим следующий интерфейс.
Свойства объекта отображаются на форме, причём разные типы данных могут иметь различное визуальное представление. В правом верхнем углу есть кнопка, нажав на которую мы перейдём в режим редактирования данных.
На рисунке показан режим редактирования и нажата кнопка в виде календаря рядом с полем даты рождения. Мы можем внести какие-либо изменения и нажать на кнопку «Save».
Но что делать, если нам не требуется отображать все свойства объекта? Для этого случая есть атрибут «Bindable». Вот пример кода установки данного атрибута для фамилии:
[Bindable(false)]
public string LastName { get; set; }
* This source code was highlighted with Source Code Highlighter.
Первый параметр показывает, производить связывание или нет. Также, если требуется сокрыть все свойства класса можно применить данный атрибут к классу в целом.
Кроме того, используя атрибут «Bindable» можно сделать некоторые свойства доступными только для чтения:
[Bindable(true, BindingDirection.OneWay)]
public string LastName { get; set; }
* This source code was highlighted with Source Code Highlighter.
В этом случае связывание происходит только в одну сторону. Теперь давайте сделаем так, чтобы в форме данных отображалось не имя свойства, а заданный нами текст. Для этого можно использовать атрибут «Display» (предварительно надо подключить сборку System.ComponentModel.DataAnnotations.dll):
public class Person
{
[Display(Name = "Имя")]
public string FirstName { get; set; }
[Display(Name = "Фамилия")]
public string LastName { get; set; }
[Display(Name = "Дата рождения")]
public DateTime DateOfBirth { get; set; }
}
* This source code was highlighted with Source Code Highlighter.
У атрибута «Display» есть и другие свойства, например можно задать описание свойств класса и порядок расположения свойств на форме данных.
[Display(Name = "Имя", Description = "Имя человека", Order = 1)]
public string FirstName { get; set; }
* This source code was highlighted with Source Code Highlighter.
Если задано описание, то оно отображается при наведении на маленький значок рядом со свойством.
Для свойства имени также задан порядковый номер. Но, так как для других свойств порядок не задан, они отображаются выше.
Отмена внесённых изменений.
Сейчас, нажав на кнопку «редактировать», мы видим внизу формы только кнопку «сохранить». Возможность отмены внесённых изменений не включена. Чтобы появилась кнопка «отменить», нам надо реализовать в классе Person интерфейс IEditableObject:
public class Person : IEditableObject
* This source code was highlighted with Source Code Highlighter.
Интерфейс содержит следующие функции:
public void BeginEdit()
{
}
public void CancelEdit()
{
}
public void EndEdit()
{
}
* This source code was highlighted with Source Code Highlighter.
Мы можем обработать момент начала редактирования (BeginEdit), конца редактирования (EndEdit) и нажатия кнопки отмены (CancelEdit).
После реализации интерфейса, как видно на рисунке, кнопка «Cancel» в режиме редактирования отображается, но саму функциональность отмены придется реализовывать самостоятельно.
Валидация данных.
Очень интересной возможностью компонента DataForm является встроенная поддержка валидации данных и вывода сообщений об ошибках. Настройки для валидации данных могут задаваться с помощью атрибутов у классов, представляющих сущности данных.
Рассмотрим атрибут «Required». Он позволяет определить обязательные свойства, то есть такие свойства, которые при редактировании пользователь обязательно должен задать. Вот пример использования данного атрибута:
[Required(ErrorMessage="Имя является обязательным")]
public string FirstName { get; set; }
* This source code was highlighted with Source Code Highlighter.
Обязательные свойства при редактировании отображаются жирным шрифтом. При этом если удалить текст из поля «Имя» и нажать кнопку «Save», появится сообщение об ошибке, которое Вы можете видеть на рисунке. В сообщении будет отображаться заданный нами текст. Если же мы определим атрибут Required без параметра ErrorMessage, пользователь увидит стандартное сообщение.
Задав атрибут «StringLength», можно указать максимальную длину текста, вводимого пользователем.
[StringLength(10)]
public string LastName { get; set; }
* This source code was highlighted with Source Code Highlighter.
А атрибут «Range» позволяет задать допустимый интервал для числовых свойств.
[Range(10,50)]
public int MyProperty { get; set; }
* This source code was highlighted with Source Code Highlighter.
Кроме того есть атрибут «RegularExpression», который позволяет использовать для валидации вводимых значение регулярные выражения.
Но атрибуты использовать не обязательно. Давайте зададим для свойства даты рождения get и set функции и произведём валидацию в коде. Для хранения даты рождения мы добавим в класс поле dateOfBirth.
private DateTime _dateOfBirth;
[Display(Name = "Дата рождения")]
public DateTime DateOfBirth
{
get
{
return _dateOfBirth;
}
set
{
if (value > DateTime.Now)
throw new InvalidOperationException("Привет тебе, гость из будущего!");
_dateOfBirth = value;
}
}
* This source code was highlighted with Source Code Highlighter.
Как видно из кода, в случае, если дата рождения больше текущей даты, мы генерируем исключение. DataForm обрабатывает исключение и показывает сообщение об ошибке.
В случае если нам надо разделить логику валидации и код класса, можно написать для этих целей дополнительный класс и определить логику валидации там. Установить класс и метод валидации мы можем с помощью атрибута:
[CustomValidation(typeof(PersonValidator),"ValidatePerson")]
public class Person
* This source code was highlighted with Source Code Highlighter.
Вот, собственно, код класса валидатора:
public class PersonValidator
{
public static bool ValidatePerson(Person p)
{
return false;
}
}
* This source code was highlighted with Source Code Highlighter.
Определить атрибут «CustomValidation» можно и у любого конкретного свойства.
Работа с набором данных.
До сих пор мы работали только с одним объектом данных. Теперь давайте посмотрим, как работать с набором объектов.
Для этого удалим наши изменения конструктора класса MainPage и добавим код создания набора объектов класса Person. А также свяжем свойство ItemsSource формы данных с созданной нами коллекцией:
public MainPage()
{
InitializeComponent();
ObservableCollection<Person> persons = new ObservableCollection<Person>();
persons.Add(new Person() { FirstName = "Иван", LastName = "Петров", DateOfBirth = DateTime.Now });
persons.Add(new Person() { FirstName = "Пётр", LastName = "Иванов", DateOfBirth = DateTime.Now });
persons.Add(new Person() { FirstName = "Владимир", LastName = "Сидоров", DateOfBirth = DateTime.Now });
mainData.ItemsSource = persons;
}
* This source code was highlighted with Source Code Highlighter.
Запустим программу и увидим, что мы можем переходить от одной записи к другой, добавлять, удалять и редактировать записи.
Настройка формы данных.
Хотелось бы отметить, что у формы данных достаточно много свойств, позволяющих задать её внешний вид. Например, свойство «Header» позволяет установить заголовок формы, а свойство «FieldLabelPosition» задаёт расположение подписей:
<dataControls:DataForm x:Name="mainData" Margin="50"
Header="Сотрудники" FieldLabelPosition="Top"></dataControls:DataForm>
* This source code was highlighted with Source Code Highlighter.
Благодаря свойству «CanUserDeleteItems», можно включить или отключить возможность удаления записей. А свойства «CommitButtonContent» и «CancelButtonContent» задают текст на кнопках «Save» и «Cancel» соответственно. Есть и другие полезные свойства, назначения которых также легко понять по их названиям.
Мы все уже давно привыкли, что текущее положение каретки в документе можно визуально определить по мигающей вертикальной линии. Помните, как она выглядит? Узкая, шириной в несколько пикселей, полоска, окрашенная инвертированным фоновым цветом. Весьма неожиданно, но в третьей версии сильверлайта мы можем самостоятельно задавать стиль каретки!
У элемента TextBox появилось свойство CaretBrush, которое позволяет задать кисть, которой будет окрашена каретка. Например, можно задать в качестве фона каретки градиент, состоящий из цветов радуги:
<TextBox FontSize="70">
<TextBox.CaretBrush>
<LinearGradientBrush
MappingMode="RelativeToBoundingBox"
StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Red" Offset="0" />
<GradientStop Color="Orange" Offset="0.170" />
<GradientStop Color="Yellow" Offset="0.332" />
<GradientStop Color="Green" Offset="0.5"/>
<GradientStop Color="Blue" Offset="0.633" />
<GradientStop Color="Indigo" Offset="0.812" />
<GradientStop Color="Violet" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</TextBox.CaretBrush>
</TextBox>
* This source code was highlighted with Source Code Highlighter.
Вы можете использовать любую доступную кисть: SolidColorBrush, LinearGradientBrush, RadialGradientBrush, ImageBrush или VideoBrush.
Сильверлайт устроен так, что по умолчанию он кэширует изображения, получаемые с сервера. Если вы задаете в качестве источника изображения для элемента Image картинку по URI-адресу, с которого она ранее уже была загружена, то ваше приложение не скачивает изображение с сервера, а берет из КЭШа. Это поведение можно очень легко изменить - достаточно задать у экземпляра BitmapImage свойство CreateOptions в BitmapCreateOptions.IgnoreImageCache, как это сделано в этом примере:
Image img = new Image();
Uri uri =
new Uri("http://YourServer.com/MyImage.png", UriKind.Absolute);
BitmapImage bi = new System.Windows.Media.Imaging.BitmapImage(uri);
bi.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
img.Source = bi;
LayoutRoot.Children.Add(img);
* This source code was highlighted with Source Code Highlighter.
Вот заметка на эту тему (en)
Опубликовано
09 мая 2009, 06:49
, автор -
Сергей Пугачёв