質問

オブジェクトに対して WPF フォームを検証しようとしています。テキストボックスに何かを入力すると、検証が開始され、フォーカスが失われ、テキストボックスに戻って、書き込んだ内容が消去されます。しかし、WPF アプリケーションをロードし、テキスト ボックスに何も書き込んだり削除したりせずに、テキスト ボックスをタブで移動するだけでは、アプリケーションは起動されません。

Customer.cs クラスは次のとおりです。

public class Customer : IDataErrorInfo
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public string Error
        {
            get { throw new NotImplementedException(); }
        }
        public string this[string columnName]
        {
            get
            {
                string result = null;

                if (columnName.Equals("FirstName"))
                {
                    if (String.IsNullOrEmpty(FirstName))
                    {
                        result = "FirstName cannot be null or empty"; 
                    }
                }
                else if (columnName.Equals("LastName"))
                {
                    if (String.IsNullOrEmpty(LastName))
                    {
                        result = "LastName cannot be null or empty"; 
                    }
                }
                return result;
            }
        }
    }

そして、これが WPF コードです。

<TextBlock Grid.Row="1" Margin="10" Grid.Column="0">LastName</TextBlock>
<TextBox Style="{StaticResource textBoxStyle}" Name="txtLastName" Margin="10"
         VerticalAlignment="Top" Grid.Row="1" Grid.Column="1">
    <Binding Source="{StaticResource CustomerKey}" Path="LastName"
             ValidatesOnExceptions="True" ValidatesOnDataErrors="True"
             UpdateSourceTrigger="LostFocus"/>         
</TextBox>
役に立ちましたか?

解決

コードの背後にロジックを少し追加することに抵抗がない場合は、実際のコードを処理できます。 ロストフォーカス 次のようなイベント:

.xaml

<TextBox LostFocus="TextBox_LostFocus" ....

.xaml.cs

private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
     ((Control)sender).GetBindingExpression(TextBox.TextProperty).UpdateSource();
}

他のヒント

残念ながら、これは仕様によるものです。WPF 検証は、コントロールの値が変更された場合にのみ実行されます。

信じられないことですが、本当です。これまでのところ、WPF の検証は大きな苦痛であり、ひどいものです。

ただし、できることの 1 つは、コントロールのプロパティからバインディング式を取得し、手動で検証を呼び出すことです。最悪ですが、うまくいきます。

を見てください。 ValidatesOnTargetUpdated ValidationRule のプロパティ。データが最初にロードされるときに検証されます。これは、空のフィールドまたは null フィールドをキャッチしようとしている場合に適しています。

バインディング要素を次のように更新します。

<Binding 
    Source="{StaticResource CustomerKey}" 
    Path="LastName" 
    ValidatesOnExceptions="True" 
    ValidatesOnDataErrors="True" 
    UpdateSourceTrigger="LostFocus">
    <Binding.ValidationRules>
        <DataErrorValidationRule
            ValidatesOnTargetUpdated="True" />
    </Binding.ValidationRules>
</Binding>

これを処理する最良の方法は、テキストボックスのLostFocusイベントで行うことであることがわかりました。次のようなことを行います

    private void dbaseNameTextBox_LostFocus(object sender, RoutedEventArgs e)
    {
        if (string.IsNullOrWhiteSpace(dbaseNameTextBox.Text))
        {
            dbaseNameTextBox.Text = string.Empty;
        }
    }

その後、エラーが表示されます

私は同じ問題を経験し、これを解決する非常に簡単な方法を見つけました。ウィンドウの Loaded イベントに、txtLastName.Text = String.Empty と入力するだけです。それでおしまい!!オブジェクトのプロパティが変更された (空の文字列に設定された) ため、検証が開始されます。

次のコードは、すべてのコントロールをループして検証します。必ずしも好ましい方法ではありませんが、うまくいくようです。TextBlocks と TextBoxes のみを実行しますが、簡単に変更できます。

public static class PreValidation
{

    public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
    {
        if (depObj != null)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                if (child != null && child is T)
                {
                    yield return (T)child;
                }

                foreach (T childOfChild in FindVisualChildren<T>(child))
                {
                    yield return childOfChild;
                }
            }
        }
    }


    public static void Validate(DependencyObject depObj)
    {
        foreach(var c in FindVisualChildren<FrameworkElement>(depObj))
        {
            DependencyProperty p = null;

            if (c is TextBlock)
                p = TextBlock.TextProperty;
            else if (c is TextBox)
                p = TextBox.TextProperty;

            if (p != null && c.GetBindingExpression(p) != null) c.GetBindingExpression(p).UpdateSource();
        }

    }
}

ウィンドウまたはコントロールで Validate を呼び出すだけで、事前に検証されます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top