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>