web-dev-qa-db-ja.com

本当に簡単なWPFフォームデータ検証-方法

私はこの本当にシンプルなクラスを持っています。Customerと呼んでみましょう。次のようになります。

namespace TestValidation
{
     class Customer
     {
        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                if (String.IsNullOrEmpty(value))
                {
                    throw new Exception("Customer name is mandatory.");
                }
            }
        }
    }
}

ここで、ユーザーがデータベースに顧客を追加できる基本フォームを作成しました。フォームには、CustomerのNameプロパティにバインドされた単純なTextBox、および「追加」ボタンが含まれます。

XAMLコードは次のとおりです。

<Window x:Class="TestValidation.MainWindow"
        xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TestValidation"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
<TextBox Margin="119,86,107,194" Name="CustomerName"
        Text="{Binding Path=Customer.Name, 
                ValidatesOnExceptions=True, 
                ValidatesOnDataErrors=True,
                UpdateSourceTrigger=PropertyChanged,
                NotifyOnValidationError=True}"
    />
        <Button Content="Add" HorizontalAlignment="Left" Margin="204,176,0,0" VerticalAlignment="Top" Width="74"/>
    </Grid>
</Window> 

Nameプロパティのセッターから、名前が私にとって必須であることを理解できるので、Name TextBoxが空白のままになっている場合に検証イベントが発生するようにします。 WPFの検証ルール-ユーザーがテキストボックスの外にフォーカスし、そこに値がない場合-境界線の色を赤に変更する必要があります。なんらかの理由で-これは起きていないので、理由がわかりません。私のプロセスの何が問題になっていますか?

今、私はWPFの検証に関する多くの良い記事を読みました( WPFでの複雑なビジネスデータルールの強制WPFのデータ検証 、Windows Presentation Foundationの検証など)しかし、それらのどれも私の問題を解決する助けにはなりませんでした。

最終的には、フォームを最初のリンク上でBrian Noyesの優れた記事のフォームのように見せたいです(10クレジットを持っていないので、写真を添付できません...申し訳ありません)。

誰かがそれが実際にどのように機能するかを私に説明できるなら、私は感謝するでしょう。

重要な注意-私は.Net framework 4を使用しているため、このバージョンに適したソリューションが必要です。

19
Bak Itzik

WPFは既にその使用方法を理解しており、実装も簡単なので、WPFの検証には IDataErrorInfo を使用することをお勧めします。

まず、検証するデータを含むクラスにインターフェイスを追加します。必要なメソッドはおそらく次のようになります。

public class Customer : IDataErrorInfo
{
    ...

    #region IDataErrorInfo Members

    string IDataErrorInfo.Error
    {
        get { return null; }
    }

    string IDataErrorInfo.this[string columnName]
    {
        get
        {
            if (columnName == "Name")
            {
                // Validate property and return a string if there is an error
                if (string.IsNullOrEmpty(Name))
                    return "Name is Required";
            }

            // If there's no error, null gets returned
            return null;
        }
    }
    #endregion
}

次に、TextBoxバインディングにValidatesOnDataErrors=Trueを設定して、Nameプロパティが変更されるたびに検証を実行する必要があります。

<TextBox Text="{Binding Path=Customer.Name, ValidatesOnDataErrors=True}" ... />

最後に、XAMLで検証テンプレートを作成し、WPFに検証エラーを描画する方法を伝えます。私が通常使用するスタイル/テンプレートは次のとおりです。

<!-- ValidatingControl Style -->
<Style TargetType="{x:Type FrameworkElement}" x:Key="ValidatingControl">
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="True">
            <Setter Property="ToolTip" Value="{Binding 
                Path=(Validation.Errors)[0].ErrorContent, 
                RelativeSource={x:Static RelativeSource.Self}}" />
        </Trigger>
    </Style.Triggers>
</Style>

また、CustomerクラスがINotifyPropertyChangedを実装し、UIの更新に正しく応答するようにしてください。私はあなたのコードにそれを見ませんが、多くの場合、人々は単純にするためにそれを省きます:)

33
Rachel

検証ルールを指定しませんでした。検証ルールは、コントロールが終了する前に呼び出され、入力を検証する任意の操作を実行できます。

簡単な例-そしてそれがあなたがしたいことだと思います-が提供されます here

2

検証には IDataErrorInfo を使用します。この link が役立ちます。

2
Sampath

Ithink問題は、クラスがINotifyPropertyChangedを実装していないために、期待どおりにバインドされていないことです。

INotifyPropertyChangedインターフェイスを実装し、プロパティが変更されて動作するはずであるときにイベントを発生させます。

http://msdn.Microsoft.com/en-us/library/ms743695(v = vs.110).aspx をご覧ください。

0
Dave
<Binding Path=Name UpdateSourceTrigger="PropertyChanged">
  <Binding.ValidationRules>
    <ExceptionValidationRule />
  </Binding.ValidationRules>
</Binding>

http://msdn.Microsoft.com/en-us/library/ms752347%28v=vs.110%29.aspx#what_is_data_binding

このブログを使用してください:prasadcsharp.blogspot.com

0
user3510437

私はこの投稿が古いことを知っていますが、ここに私とうまくいったものがあります。遅延や長いコーディングはありませんが、double値でのみ使用しました。必要に応じて変更できます。

 private void search_box_TextChanged(object sender, TextChangedEventArgs e)
    {
        //  box text and background to normal state if user types numbers
        search_box.Foreground = Brushes.Black;
        search_box.Background = Brushes.White;

          if (search_id.IsSelected == true)
        {
            try
            {
                //convert while user is typing
                if (string.IsNullOrEmpty(search_box.Text)==false)
              Convert.ToDouble(search_box.Text);
                search_error.Text = null;
            }

            //if user types a letter or a space or a symbol  ====>
            catch (Exception)
            {
          //  user cant type any value other than numbers as exception prevents it and clears the box text value <======
                search_box.Text = null;
                search_box.Foreground = Brushes.White;
                search_box.Background = Brushes.Red;
                search_error.Text="id is numberic value";
            }
        }

        }

それが役に立てば幸い。

0
homa