0

私は WPF を初めて使用し、(私の意見では) 奇妙な問題を抱えています。ローカル プロパティ (名前: XmlText) を TextBox.Text プロパティにバインドし、次のような検証規則で値を検証したいと考えています。

<TextBox Height="23" Width="301" Margin="78,14,0,0" Name="tbXMLFile" HorizontalAlignment="Left" VerticalAlignment="Top" TextChanged="tbXMLFile_TextChanged">
    <TextBox.Style>
        <Style TargetType="{x:Type TextBox}">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="true">
                    <Setter Property="ToolTip"
                            Value="{Binding RelativeSource={RelativeSource Self},
                                            Path=(Validation.Errors),
                                            Converter={StaticResource ErrorsToStringConverter}}"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </TextBox.Style>
    <TextBox.Text>
        <Binding Path="XmlText" UpdateSourceTrigger="PropertyChanged">
            <Binding.ValidationRules>
                <local:RegexValidationRule Dateiendung="xml"></local:RegexValidationRule>
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

プロパティ XmlText が新しい値を取得するたびに、検証は何もしませんが、TextBox に手動でテキストを入力すると、検証されます。

TextChanged-Event を削除するか、次のコードをイベントに追加すると、検証が機能しなくなります。

XmlText = ((TextBox)sender).Text;

プログラムがこのように動作する理由を誰かが説明できますか?

4

1 に答える 1

0

本当の問題は ValidationRules です: それらはあなたが考えていることをするために設計されたものではありません! 詳細については、この記事をご覧ください: http://msdn.microsoft.com/en-us/library/system.windows.controls.validationrule.aspx

(WPF データ バインディング モデルを使用する場合、ValidationRules をバインディング オブジェクトに関連付けることができます。カスタム ルールを作成するには、このクラスのサブクラスを作成し、Validate メソッドを実装します。必要に応じて、組み込みの ExceptionValidationRule を使用します。ソースの更新中にスローされた、またはソース オブジェクトの IDataErrorInfo 実装によって発生したエラーをチェックする DataErrorValidationRule. バインディング エンジンは、バインディング ターゲット プロパティ値である入力値を転送するたびに、バインディングに関連付けられている各 ValidationRule をチェックします。 、バインディング ソース プロパティに。)

バインドされたオブジェクトのクラスにインターフェイスを実装するSystem.ComponentModel.IDataErrorInfoと、(バインドされたプロパティの割り当てと UI からの) 検証がキャッチされます。

これらは 2 つの方法にすぎません。プロパティの例を示します。

public class TestObject : INotifyPropertyChanged, IDataErrorInfo
{
    private string _xmlText;

    public string XmlText
    {
        get
        {
            return _xmlText;
        }
        set
        {
            if (value != _xmlText)
            {
                _xmlText = value;
                NotifyPropertyChanged("XmlText");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void NotifyPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (null != handler)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }


    public string Error
    {
        get { throw new NotImplementedException(); }
    }

    public string this[string columnName]
    {
        get
        {
            string result = null;
            if (columnName == "XmlText")
            {
                if (XmlText.Length > 5)
                    result = "Too much long!";
            }
            return result;
        }
    }
}

これで、バインディングの検証が完全に機能するはずです。

<TextBox.Text>
    <Binding Path="XmlText"
             UpdateSourceTrigger="PropertyChanged"
             ValidatesOnDataErrors="True"
             Mode="TwoWay" />
    </Binding>
</TextBox.Text>
于 2012-08-24T07:41:47.920 に答える