4

Integerプロパティにバインドされたテキストボックスがあります。ユーザーがテキストボックスに整数に変換できないもの(名前など)を入力すると、例外がスローされ、元のプロパティ値は変更されません。そのプロパティに接続されているコマンドを無効にできるように、例外をキャッチしたいですか?一般的に、可能であればプロパティが定義されているビューモデルからそれを行うにはどうすればよいですか?

4

3 に答える 3

5

私は最近同じ問題に直面し、それを解決するためにビヘイビアーを使用しました(ただし、必要がなければ必要ありません。異なるビュー間で必要なコードを再利用するためだけのものでした)。主なアイデアは、ViewModelでいくつかのメソッドを定義して、ViewModelが検出できない入力のエラーをビューが通知できるようにすることです。

したがって、最初にViewModelでこれらのメソッドを定義します。簡単にするために、エラーの数のみを追跡しますが、エラーに関する詳細情報(実際のエラーなど)を保存できます。

private int _errorCount = 0;
void AddUIValidationError()
{
   _errorCount++;
}

void RemoveUIValidationError()
{
   _errorCount--;
}

次に、ビューでに登録しますSystem.Windows.Controls.Validation.ErrorEvent。これは、コンポーネント(以前はデータエラーを通知するように構成されていた)がエラー(例外検証エラーなど)を検出したときに通知するルーティングイベントです。

public partial class MyView : UserControl // or whatever it is
{
    public MyView(MyViewModel viewModel)
    {
        // Possibly ensure that viewModel is not null
        InitializeComponent();
        _myViewModel = viewModel;

        this.AddHandler(System.Windows.Controls.Validation.ErrorEvent, new RoutedEventHandler(OnValidationRaised));
    }

    private MyViewModel _myViewModel;

    private void OnValidationRaised(object sender, RoutedEventArgs e)
    {
        var args = (System.Windows.Controls.ValidationErrorEventArgs)e;

        if (_myViewModel != null)
        {

            // Check if the error was caused by an exception
            if (args.Error.RuleInError is ExceptionValidationRule)
            {
                // Add or remove the error from the ViewModel
                if (args.Action == ValidationErrorEventAction.Added)
                    _myViewModel.AddUIValidationError();
                else if (args.Action == ValidationErrorEventAction.Removed)
                    _myViewModel.RemoveUIValidationError();
            }
        }
    }
}

コマンドのCanExecuteメソッドで、ViewModelの_errorCountフィールドが0より大きいかどうかを確認します。その場合、コマンドを無効にする必要があります。

ValidatesOnExceptions=True, NotifyOnValidationError=Trueこれが機能するように、バインディングに追加する必要があることに注意してください。元:

<TextBox Text="{Binding Path=MyProperty, ValidatesOnExceptions=True, NotifyOnValidationError=True}" />

編集:

Rileyが述べたこととは別に、別のアプローチ(これも良いですが、モデルの各整数プ​​ロパティをViewModelの新しい文字列プロパティにマップする必要があります)は、ValidationRulesを使用することです。ValidationRuleプロパティセッターを解析して呼び出す前にチェックされるを追加できます。したがって、たとえば、ValidationRuleから継承し、Validateメソッドを実装して、文字列を整数に解析できるようにすることができます。例:

public class IntegerValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        int number;
        if(Int32.TryParse((string)value, out number) == false)
            return new ValidationResult(false, "It is not a valid number");
        return new ValidationResult(true, null);
    }
}

次に、ビューでIntegerValidationRuleが定義されている名前空間を定義します。

<UserControl 
...
    xmlns:rules="clr-namespace:MyApplication.ValidationRules"
...>

そして、バインディングでルールを使用します。

<TextBox>
    <TextBox.Text>
       <Binding Path="MyProperty">
           <Binding.ValidationRules>

              <rules:IntegerValidationRule/>
           </Binding.ValidationRules>
       </Binding>
    </TextBox.Text>
</TextBox>

ただし、とにかく、検証する文字列以外の型ごとにクラスを作成する必要があり、Binding構文は少し長く見えるようになりました。

ご挨拶

于 2012-11-11T22:09:12.687 に答える
1

私がWebで見つけた「最良の」ソリューションは、http://www.wpfsharp.com/2012/02/03/how-to-disable-a-button-on-textbox-validationerrors-in-wpfで説明されています。 //

つまり、検証エラーは、ViewModelではなくViewで処理されます。独自のValidationRuleは必要ありません。XAMLのボタンにスタイルを追加するだけです。

<Button.Style>
            <Style TargetType="{x:Type Button}">
                <Setter Property="IsEnabled" Value="false" />
                <Style.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding ElementName=TextBox1, Path=(Validation.HasError)}" Value="false" />
                            <Condition Binding="{Binding ElementName=TextBox2, Path=(Validation.HasError)}" Value="false" />
                        <Setter Property="IsEnabled" Value="true" />
                    </MultiDataTrigger>
                </Style.Triggers>
            </Style>
        </Button.Style>

これがこの質問に出くわした人に役立つことを願っています(私はそれが何年も後にOPを助ける可能性が低いことを知っています)。

于 2015-05-09T15:51:41.213 に答える
0

ビューからではなく、ビューモデルからコマンドを呼び出すことを検討してください。

private int _myProperty;
public int MyProperty
{
    get
    {
        return _myProperty;
    }
    set
    {
        _myProperty = value;
        // See if the value can be parsed to an int.
        int potentialInt;
        if(int.TryParse(_myProperty, out potentialInt))
        {
            // If it can, execute your command with any needed parameters.
            yourCommand.Execute(_possibleParameter)
        }
    }
}

これにより、整数に解析できないものをユーザーが入力した場合に処理できるようになり、ユーザーが入力したものが整数の場合にのみコマンドを実行できます。

(私はこのコードをテストしませんでしたが、役立つかもしれないと思います。)

于 2012-11-12T01:36:27.547 に答える