前書き
必要な小数検証を格納するDecimalTextBox を作成したので、毎回検証を再作成する必要がなく、代わりに を使用できます。Josh Smith によるこの記事によると、この検証にはバインドする必要があるプロパティがあるため、それらにバインドできるように作成しました。UserControl
UserControl
DependencyProperties
問題
コントロールの検証が異常に動作しています。に誤った値を入力するTextBox
と、エラーとして表示されます。ただし、コードで値を元に戻そうとしても、テキスト ボックスに表示される値は変更されません。
このエラーを引き起こすために実行する手順は次のとおりです (この例では、1 は無効な値です)。
- フォームをロードします。デフォルト値は0です。
- テキストボックスに1を入力します (検証結果がエラーであるためにテキストボックスが赤くなります)
- コードでは、テキスト ボックスにバインドされたプロパティを0に設定します。
- フォームはまだ赤いテキストボックスに1を表示します
コード例
ここからダウンロードできる問題を示す例を用意しました。
ここにコードの一部を掲載します。さらに必要な場合はお知らせください。
ValidationTestControl の XAML
<UserControl x:Class="WPFTestProject.ValidationTestControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:v="clr-namespace:WPFTestProject"
x:Name="ValidationTest"
Height="50" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Text="Type 'Banana' here: "></TextBlock>
<TextBox MinWidth="100">
<TextBox.Text>
<Binding ElementName="ValidationTest" Path="Text" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay" ValidatesOnDataErrors="True" ValidatesOnExceptions="True">
<Binding.ValidationRules>
<v:NotBananaValidationRule>
<v:NotBananaValidationRule.NotWhatBinding>
<v:NotBananaBinding x:Name="NotBananaValidationBinding"></v:NotBananaBinding>
</v:NotBananaValidationRule.NotWhatBinding>
</v:NotBananaValidationRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<TextBlock Text=" (the text will give error when = 'Banana')"></TextBlock>
</StackPanel>
</Grid>
ValidationTestControls コード ビハインド
(はい、MVVM についてはよくわかりませんが、このスタンドアロン コントロールでは問題ないと感じました)
public partial class ValidationTestControl : UserControl
{
public ValidationTestControl()
{
InitializeComponent();
Banana = "Banana";
Binding BananaBinding = new Binding("Banana");
BananaBinding.Source = this;
NotBananaValidationBinding.SetBinding(NotBananaBinding.NotWhatProperty, BananaBinding);
}
public static DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(ValidationTestControl), new PropertyMetadata());
public static DependencyProperty BananaProperty = DependencyProperty.Register("Banana", typeof(string), typeof(ValidationTestControl), new PropertyMetadata());
public string Text
{
get
{
return (string)GetValue(TextProperty);
}
set
{
SetValue(TextProperty, value);
}
}
public string Banana
{
get
{
return (string)GetValue(BananaProperty);
}
set
{
SetValue(BananaProperty, value);
}
}
}
バインド用に作成された ValidationRule と FrameWorkElement
public class NotBananaValidationRule:ValidationRule
{
private NotBananaBinding _notWhatBinding;
public NotBananaBinding NotWhatBinding
{
get { return _notWhatBinding; }
set { _notWhatBinding = value; }
}
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
string what = value.ToString();
if(what == _notWhatBinding.NotWhat||string.IsNullOrEmpty(what))
return new ValidationResult(false,
"Please enter a string that is not " + _notWhatBinding.NotWhat);
else
return new ValidationResult(true, null);
}
}
public class NotBananaBinding : FrameworkElement
{
public static readonly DependencyProperty NotWhatProperty = DependencyProperty.Register(
"NotWhat", typeof(string), typeof(NotBananaBinding), new UIPropertyMetadata());
public string NotWhat
{
get { return (string)GetValue(NotWhatProperty); }
set { SetValue(NotWhatProperty, value); }
}
public NotBananaBinding() { }
}
基本的に、このコードが行うことは、「Banana」と入力したかどうかを確認し、検証エラーを返すことです。コントロールを使用するときに依存関係プロパティにバインドできるようにするため、コントロールは依存関係プロパティを公開します。FrameworkElement
NotBananaBindingを使用すると、依存関係プロパティを作成できます (検証DependencyObject
用にバインドできるためです。ValidationRuleには、依存関係プロパティを格納し、それを検証メソッドで使用するNotBananaBindingプロパティがあります。
私のプロパティ名はちょっとくだらないことを知っています、ごめんなさい。問題は、この例がエラーをうまく表示していることです。急いで例を作ったので、変数にうまく名前を付けませんでした。コードがくだらないと思われる場合は、こちらからサンプルをダウンロードしてください 。
これまでにわかったこと
基本的に、この問題は、実際に値を変更していないことが原因のようです。
プロパティで OnPropertyChanged を呼び出しても、値が変わらないため、検証を再評価しようとしません。
明らかに、値を任意の有効な値に変更してから、希望する値に変更すると機能しますが、呼び出しの検証を手動で取得し、値を再評価してから変更する方法があることを望んでいましたなど。それを前後に変更するのはちょっと面倒です。
結論
私は何か間違ったことをしていますか (おそらく、Josh Smith の投稿から検証とバインディングを実装する方法について何か)
これはただの ac# バグですか、それとも意図した動作ですか? もしそうなら、なぜですか?
それを修正するエレガントな方法はありますか?
u_u