Silverlight4 Validation付きユーザコントロール
コントロール自身にValidation機能を持たせたユーザコントロールの例
開発環境:VisualStudio2010 Silverlight4

最近SilverLight4のアプリを開発してるのですが、日本語情報はすくないですねぇ。しかたなく英文と格闘する毎日を送っています。
情報をもらってばかりいるのは気が引けますので、少しづつですが私も情報を発信していきます。ほんとうは半年後の自分のためでもあるんでしけどね。まずは出来立てのユーザコントロールからどうぞ。
使用している技術内容
- ユーザコントロール
- Varidation
- Entity
- 依存関係プロパティ
- Bindをコードで記述
などにご注目ください。ちょっとてんこもりすますね^^;
直接入力やElementバインディングでも使用できることを確認しました。データバインディングのテストはしてませんが、たぶん大丈夫でしょう。
TestControl1.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Windows.Data;
using System.ComponentModel.DataAnnotations;
using System.ServiceModel.DomainServices.Client;
namespace SilverlightApplication1.Controls
{
/// <summary>
/// 内部にエンティティデータを持つユーザコントロールの例
/// コントロール単独でVlidation機能を実装。
/// Emptyと1以外のデータはエラーになる。
/// 2011/02/22 Visualstudio 2010 + Silverlight4
/// </summary>
public partial class testControl1 : UserControl
{
public testControl1() {
InitializeComponent();
//InDataはXAML側でリソースとして定義してある。
InData = new TestControlEntity();
InData.PropertyChanged += new PropertyChangedEventHandler(InData_PropertyChanged);
//デザインモードの時はバインドしない。
//(コードによるBindingの例)
if (!DesignerProperties.IsInDesignTool) {
Binding b = new Binding();
b.Source = InData;
b.Path = new PropertyPath("InText");
b.Mode = BindingMode.TwoWay;
b.NotifyOnValidationError = true;
b.ValidatesOnDataErrors = true;
b.ValidatesOnExceptions = true;
b.ValidatesOnNotifyDataErrors=true;
textBox1.SetBinding(TextBox.TextProperty,b);
}
}
void InData_PropertyChanged(object sender, PropertyChangedEventArgs e) {
if (e.PropertyName == "Text") {
this.Text = ((TestControlEntity)sender).InText;
}
}
#region 依存関係プロパティ(Text) 黄金パターン^^V
//-----------------------------------------------------------------------------------
public readonly static DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(testControl1),
new PropertyMetadata("",
new PropertyChangedCallback(testControl1.OnTextChangedStatic)));
private static void OnTextChangedStatic(DependencyObject d, DependencyPropertyChangedEventArgs e) {
((testControl1)d).OnTextChanged(e);
}
private void OnTextChanged(DependencyPropertyChangedEventArgs e) {
//InData.InText = e.NewValue.ToString(); //<--これはダメ ElementBindingの例で落ちる(右の例)
if (textBox1 != null) {
textBox1.Text = e.NewValue.ToString();
}
}
[Category("共通")]
public object Text {
set { SetValue(TextProperty, value); }
get { return GetValue(TextProperty); }
}
//-----------------------------------------------------------------------------------
#endregion
}
// //////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// ユーザコントロール内部で使用するEntity
/// </summary>
public class TestControlEntity : INotifyPropertyChanged
{
public TestControlEntity(){}
private string _InText="";
public string InText {
set {
//内部データとコントロールの表示を一致させる場合はこっちを使う
//正しくない値でもセットして通知
//if (_InText == value) { return; }
//_InText = value;
//OnPropertyChanged("Text");
if (!String.IsNullOrEmpty(value) && value != "1") {
throw new ArgumentException("TextはEmptyまたは1でなければなりません。:["+value.ToString()+"]");
}
//正しい値なのでセットして通知
_InText = value;
OnPropertyChanged("Text");
}
get {
return _InText;
}
}
#region INotifyPropertyChanged メンバー
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string Name) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(Name));
}
}
#endregion
}
}
testControl1.xaml
使用するには
xmlns:Local=”clr-namespace:SilverlightApplication1.Controls”
あたりを修正しないといけませんね。
<UserControl x:Class="SilverlightApplication1.Controls.testControl1"
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"
mc:Ignorable="d"
xmlns:Local="clr-namespace:SilverlightApplication1.Controls"
d:DesignHeight="57" d:DesignWidth="226">
<UserControl.Resources>
<Local:TestControlEntity x:Name="InData" />
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="#FFCDF2DB">
<TextBlock Height="21" HorizontalAlignment="Stretch" Name="textBlock1" Text="Emptyと1以外はエラーとなるTextBox" VerticalAlignment="Stretch" TextWrapping="Wrap" Margin="0,0,0,36" Padding="2" />
<TextBox Height="24" Margin="19,23,23,10" Name="textBox1" />
</Grid>
</UserControl>
実行例 Xaml
下記のコードは使用例です。実際に実行する時は、このユーザコントロールを使用するページを作成してみてください。
下記のカット&ペーストでは動きませんよ。
<navigation:Page x:Class="SilverlightApplication1.Views.Page4"
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"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
d:DesignWidth="640" d:DesignHeight="480"
Title="Page4 Page" xmlns:my="clr-namespace:SilverlightApplication1.Controls">
<Grid x:Name="LayoutRoot">
<my:testControl1 HorizontalAlignment="Left" Margin="79,142,0,0" x:Name="testControl11" VerticalAlignment="Top" TabIndex="2" />
<TextBox Height="24" HorizontalAlignment="Left" Margin="79,100,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" TabIndex="1" Text="ダミーパーキング場所" />
<TextBox Height="24" HorizontalAlignment="Left" Margin="79,217,0,0" Name="textBox2" VerticalAlignment="Top" Width="120" TabIndex="3" Text="ダミーパーキング場所" />
<my:testControl1 HorizontalAlignment="Left" Margin="439,142,0,0" x:Name="testControl12" VerticalAlignment="Top" TabIndex="5" Text="{Binding Path=Text, ElementName=textBox3}" />
<TextBox Height="24" HorizontalAlignment="Left" Margin="509,100,0,0" Name="textBox3" VerticalAlignment="Top" Width="52" TabIndex="4" />
<TextBox Height="24" HorizontalAlignment="Left" Margin="444,217,0,0" Name="textBox4" VerticalAlignment="Top" Width="120" TabIndex="6" Text="ダミーパーキング場所" />
<TextBlock Height="23" HorizontalAlignment="Left" Margin="380,100,0,0" Name="textBlock1" Text="Elementバインディング" VerticalAlignment="Top" />
</Grid>
</navigation:Page>

