WPF ユーザーコントロールの検証ロジックにパラメータを渡したい
WPF(.NET4.5/C#)でユーザコントロールを作成しています。
テキストボックスを拡張したもので、入力値の検証も実装します。
この検証ロジックに、次のような形でパラメータを渡したいと考えています。
<local:UserControl1 Value="{Binding Foo}" TargetType="{x:Type local:AnyType}" />
TargetType
プロパティに、検証ロジックをカスタマイズするクラスを指定できる仕組みです。
この仕組みを実装するにあたり、このサイトの解説記事を参考にしました。
できあがったコードが次の通りです。
UserControl1.xaml
<UserControl x:Class="WpfApplication1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBox>
<TextBox.Text>
<Binding Path="Value"
UpdateSourceTrigger="LostFocus"
RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}"
NotifyOnValidationError="True"
>
<Binding.ValidationRules>
<local:HogeRule>
<local:HogeRule.TargetType>
<local:DependencyType Value="{Binding TargetType, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"/>
</local:HogeRule.TargetType>
</local:HogeRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</Grid>
</UserControl>
コードビハインド
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
// Value 依存関係プロパティ
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value",
typeof(object),
typeof(UserControl1),
new FrameworkPropertyMetadata(default(object), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
// Value CLRプロパティ
public object Value
{
get { return this.GetValue(ValueProperty); }
set { this.SetValue(ValueProperty, value); }
}
// TargetType 依存関係プロパティ
public static readonly DependencyProperty TargetTypeProperty = DependencyProperty.Register(
"TargetType",
typeof(Type),
typeof(UserControl1),
new FrameworkPropertyMetadata(default(object), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
/// TargetType CLRプロパティ
public Type TargetType
{
get { return (Type)this.GetValue(TargetTypeProperty); }
set { this.SetValue(TargetTypeProperty, value); }
}
}
基本となる検証ルール
public class HogeRule : ValidationRule
{
public HogeRule()
{
this.TargetType = new DependencyType();
}
public DependencyType TargetType { get; set; }
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
// TargetType.Valueを使って処理をカスタマイズ
}
}
Type型をデータバインドで渡すために使うDependencyObject
public class DependencyType : DependencyObject
{
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value",
typeof(Type),
typeof(DependencyType),
new FrameworkPropertyMetadata(default(object), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public Type Value
{
get { return (Type)this.GetValue(ValueProperty); }
set { this.SetValue(ValueProperty, value); }
}
}
しかし、このコードを動かしても、HogeRule.Validate
が実行された時点で、TargetType.Value
はnull
になっています。
UserControl1.xaml
の
<local:DependencyType Value="{Binding TargetType, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"/>
の行を
<local:DependencyType Value="{x:Type local:AnyType}"/>
と固定で書いた場合には正常に動作するので、ここのバインディングがうまくいっていないのだと思います。
しかし、どこか違っているのか分かりません。
ただ、やりたいことは、ユーザコントロールの利用者が検証用のパラメータを指定できるようにしたいだけなので、全く別のアプローチでも構いません。