Kay Framework や Django の ModelForm を使っていると、「これ .NET にも欲しい」と良く思う。そういえば、Silverlight Tools には DataForm っていうコントロールがあったな。
試しに使ってみた。
MainPage.xaml
<UserControl x:Class="DataFormSample.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <Grid x:Name="LayoutRoot" Background="White"> <data:DataForm x:Name="_dataForm" Header="タスク登録" LabelPosition="Left" CommitButtonContent="保存" CancelButtonContent="キャンセル" AutoEdit="False" AutoCommit="False" AutoGenerateFields="True" DescriptionViewerPosition="BesideLabel"/> </Grid> </UserControl>
MainPage.xaml.cs
using System; using System.Windows.Controls; using System.ComponentModel.DataAnnotations; using System.ComponentModel; using System.Collections.ObjectModel; namespace DataFormSample { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); this._dataForm.ItemsSource = new ObservableCollection<Task>() { new Task(){ Name="DataFormを試す", Completed=false, Deadline=DateTime.Today.AddDays(1), } }; } } public class Task : INotifyPropertyChanged { // 入力必須項目なので RequiredAttribute を付与 // StringLengthAttribute で文字数も制限 private string _name; [Display(Name = "名称", Description = "タスクの名称")] [Required(ErrorMessage = "タスクの名称を入力して下さい。")] [StringLength(255, MinimumLength = 1, ErrorMessage = "名称は1文字以上、255文字以内で入力して下さい。")] public string Name { get { return _name; } set { if (_name != value) { Validate(value, "Name"); _name = value; OnPropertyChanged("Name"); } } } private bool _completed; [Display(Name = "完了済み", Description = "完了済みかどうか")] public bool Completed { get { return _completed; } set { if (_completed != value) { _completed = value; OnPropertyChanged("Completed"); } } } private DateTime _deadline; [Display(Name = "期限", Description = "タスクの期限")] public DateTime Deadline { get { return _deadline; } set { if (_deadline != value) { _deadline = value; OnPropertyChanged("Deadline"); } } } /// <summary> /// 値を検証します。 /// </summary> /// <param name="value">検証する値</param> /// <param name="propertyName">プロパティ名</param> private void Validate(object value, string propertyName) { Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = propertyName, }); } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { var h = PropertyChanged; if (h != null) { h(this, new PropertyChangedEventArgs(propertyName)); } } } }
実行画面がこちら。
最初は入力できないようになっている。右上の鉛筆ボタンを押すと入力モードに移動。
必須項目の名称を空欄にしてみる。
入力が検証されて、ページ下にエラーメッセージが表示された。
DataForm の使い方は簡単だった。編集したいクラスのコレクションを ItemsSource にバインドするだけ。デフォルトだと、クラスのプロパティをもとに、ラベルや入力欄を生成してくれた。
ObservableCollection
また、System.CompolentModel.DataAnnotations 名前空間内に定義されている属性を使えば、ラベルの内容を変更したり、保存時に入力検証を行える。
久しぶりに「スゴイ!」って思えるコントロールに出会えた。多分、チャート以来だ。データを個別に入力するようなプロジェクト(例えば得意先入力とか)は、DataForm をカスタマイズして使えば十分じゃないかな。