2017-06-07 22 views
1

私はいくつかのテキストフィールドとOKとCancelボタンを持つウィンドウを持っています。 [OK]をクリックすると、自分のフィールドを検証し、有効であればそれを行い、そうでなければエラーメッセージを表示する必要があります。私のViewModelでプロパティが2回呼び出されないようにする

私は

public ICommand OKCommand { get; private set; } 
public Action ErrorAction { get; set; } 

OKCommand = new BaseCommand(_ => 
{    
    if (string.IsNullOrEmpty(ErrorMessage)) 
    { 
     // Do stuff with the contents of the fields 
     ... 
    } 
    else ErrorAction(); 
}); 

public string ErrorMessage 
{ 
    get 
    { 
     // Gets the error message for the fields 
     ... 
    } 
} 

し、エラーがあるとき、私は私の問題はErrorMessageが最初OKCommandで、二回

if (ViewModel.ErrorAction == null) ViewModel.ErrorAction = new Action(() => MessageDialog.ShowError(ViewModel.ErrorMessage)); 

と呼ばれているんだ後ろの私のコード内に持っていますやはりErrorActionである。私は考えることができる

唯一の解決策は、

  1. 2番目の呼び出しを受け入れている - それは世界の終わりではありません。
  2. OKCommandにエラーがあるかどうかを確認し、私はどちらかとは思わない、両方の仕事は素晴らしいですが、この

    private bool HasError 
    { 
        get 
        { 
         // Do the same as ErrorMessage but populate ErrorMessage and return a bool 
         ... 
        } 
    } 
    
    OKCommand = new BaseCommand(_ => 
    {    
        if (!HasError) 
        { 
         // Do stuff with the contents of the fields 
         ... 
        } 
        else ErrorAction(); 
    }); 
    

    のような適切な

何かがErrorMessage場合に設定 - 最初は2回目の呼び出しを持っています2つめは間接的なレベルを追加します。選択肢はありますか?

+0

'ErrorAction'を' Action 'と宣言し、' ErrorCommand'に 'ErrorMessage'を明示的に渡すことができます。 – Evk

+0

もう1つの方法は、関連するプロパティーが変更されたときに 'ErrorMessage'をキャッシュしてキャッシュをリセットすることです(プロパティーが変更されたときに' _errorMessage'をヌルに、 'ErrorMessage'ゲッターで' _errorMessage'がヌルの場合のみ新しいメッセージを計算する)。 – Evk

+1

なぜErrorMessageが2回呼び出されたのですか?これはなぜ問題ですか? 2つのメッセージが表示されるのか、それとも何が問題なのですか? – mm8

答えて

0

最終的には、私の選択したオプションのどれも現在のソリューションよりはるかに優れていると私は思いました。

今後、このarticleには、データ検証の代替方法が記載されています。しかし、残念なことに私の要件は、これらが私にとっては簡単な選択肢ではないことを意味していました。

0

のTextBoxのテキストを検証する簡単な方法があります:

それは背後にあるValidationRule

You can directly see that there is an error(Error in MouseOverMessage) and the Button is disabled

<Window x:Class="TestWpf.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:TestWpf" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <local:MyValidatorProperties x:Key="properties"/> 
     <local:MyCustomValidationRule x:Key="validator" /> 
     <Style x:Key="textBoxInError" TargetType="{x:Type TextBox}"> 
      <Style.Triggers> 
       <Trigger Property="Validation.HasError" Value="true"> 
        <Setter Property="BorderBrush" Value="Red"/> 
        <Setter Property="BorderThickness" Value="2" /> 
        <Setter Property="ToolTip" 
         Value="{Binding RelativeSource={x:Static RelativeSource.Self}, 
         Path=(Validation.Errors)[0].ErrorContent}"/> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
     <ControlTemplate x:Key="validationTemplate"> 
      <DockPanel> 
       <TextBlock Foreground="Red" FontSize="17">!</TextBlock> 
       <AdornedElementPlaceholder/> 
      </DockPanel> 
     </ControlTemplate> 
    </Window.Resources> 
    <Grid> 
     <TextBox x:Name="tbName" Height="23" Validation.ErrorTemplate="{StaticResource validationTemplate}" Style="{StaticResource textBoxInError}" Margin="10,10,349,286"> 
      <TextBox.Text> 
       <Binding Path="myName" Source="{StaticResource properties}" 
         UpdateSourceTrigger="PropertyChanged" > 
        <Binding.ValidationRules> 
         <local:MyCustomValidationRule Type="myName" ValidatesOnTargetUpdated="True" /> 
        </Binding.ValidationRules> 
       </Binding> 
      </TextBox.Text> 
     </TextBox> 
     <Button x:Name="btnCreate" Content="Create" Width="58" Height="23" Margin="174,10,285,286" > 
      <Button.Style> 
       <Style TargetType="Button"> 
        <Setter Property="IsEnabled" Value="False"/> 
        <Style.Triggers> 
         <MultiDataTrigger> 
          <MultiDataTrigger.Conditions> 
           <Condition Binding="{Binding Path=(Validation.HasError), ElementName=tbRepositoryName}" Value="False"/> 
          </MultiDataTrigger.Conditions> 
          <Setter Property="IsEnabled" Value="True"/> 
         </MultiDataTrigger> 
        </Style.Triggers> 
       </Style> 
      </Button.Style> 
     </Button> 
    </Grid> 
</Window> 

コードと呼ばれています:

ValidatiorClass:

using System.Globalization; 
using System.Text.RegularExpressions; 
using System.Windows.Controls; 


namespace TestWpf 
{ 
    class MyCustomValidationRule : ValidationRule 
    { 
     public string Type { get; set; } 
     public override ValidationResult Validate(object p_value, CultureInfo p_cultureInfo) 
     { 
      switch (Type) 
      { 
       case "myName": 
        string a_strValue = p_value as string; 
        if (!string.IsNullOrEmpty(a_strValue)) 
        { 
         Match a_match = Regex.Match((string)p_value, @"^[a-zA-Z\d]+$"); 
         return a_match.Success ? new ValidationResult(true, "Name is valid!") : new ValidationResult(false, $"Input should be a Valid Name (a-z, A-Z, 0-9)"); 
        } 
        return new ValidationResult(false, "Empty name!"); 
       default: 
        return new ValidationResult(false, $"UnkownValidation Parameter: " + Type); 
      } 
     } 
    } 
} 

テキストボックスにバインドされたプロパティ:

using System.ComponentModel; 

namespace TestWpf 
{ 
    class MyValidatorProperties : INotifyPropertyChanged 
    { 
     private string m_myName = ""; 

     public string myName 
     { 
      get 
      { 
       return m_myName; 
      } 
      set 
      { 
       if (m_myName != value) 
       { 
        m_myName = value; 
        OnPropertyChanged("myName"); 
       } 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
     private void OnPropertyChanged(string info) 
     { 
      PropertyChanged?.Invoke(null, new PropertyChangedEventArgs(info)); 
     } 
    } 
} 

がPS:

<Button x:Name="btnCreate" Content="Create" Width="58" Height="23" Click="btnCreate_Click" /> 
ボタンを無効にし、代わりにメッセージを表示したくない場合は、とボタンを置き換えることができます

さらに、メソッドを追加します。

private void btnCreate_Click(object sender, RoutedEventArgs e) 
{ 
    if(System.Windows.Controls.Validation.GetHasError(tbName)) 
    { 
     //Show Message 
    } 
} 
関連する問題