2017-10-27 1 views
1

Ich habe Modell EditableSong benannt, die von ValidatableModel Klasse abgeleitet wird, die INotifyPropertyChanged und INotifyDataErrorInfo implementiert.Anruf Validierung auf, wenn das Fenster geladen wird, WPF INotifyDataErrorInfo

class EditableSong : ValidatableModel 
{ 
    CommandRelay addcommand = null; 

    public ICommand AddCommand 
    { 
     get { return addcommand; } 
    } 

    public EditableSong() 
    { 
     addcommand = new CommandRelay(Add, CanAdd); 
    } 

    private void Add(object obj = null) 
    { 
     MessageBox.Show("Succesfully Added!"); 
    } 

    private bool CanAdd(object obj = null) 
    { 
     return !HasErrors; 
    } 

    private string title; 
    [Required] 
    [MaxLength(45)] 
    public string Title 
    { 
     get { return title; } 
     set 
     { SetProperty(ref title, value); } 
    } 

    private string lyrics; 
    [MaxLength(3000)] 
    public string Lyrics 
    { 
     get { return lyrics; } 
     set { SetProperty(ref lyrics, value); } 
    } 

    private string artist; 

    [Required] 
    public string Artist 
    { 
     get { return artist; } 
     set {SetProperty(ref artist, value); } 
    } 
} 

Und hier ist ValidatableModel Klasse:

class ValidatableModel : BindableBase, INotifyDataErrorInfo 
{ 
    private Dictionary<string, List<string>> _errors = new Dictionary<string, List<string>>(); 

    public bool HasErrors 
    { 
     get { return _errors.Count >0; ; } 
    } 

    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged; 

    protected override void SetProperty<T>(ref T member, T val, 
     [CallerMemberName] string propertyName = null) 
    { 

     base.SetProperty(ref member, val, propertyName); 
     ValidateProperty(propertyName, val); 
    } 

    public IEnumerable GetErrors(string propertyName) 
    { 
     if (_errors.ContainsKey(propertyName)) 
      return _errors[propertyName]; 
     else 
      return null; 
    } 

    protected void ValidateProperty<T>(string propertyName, T value) 
    { 

     var results = new List<ValidationResult>(); 

     ValidationContext context = new ValidationContext(this); 
     context.MemberName = propertyName; 
     Validator.TryValidateProperty(value, context, results); 

     if (results.Any()) 
     { 
      _errors[propertyName] = results.Select(c => c.ErrorMessage).ToList(); 
     } 
     else 
     { 
      _errors.Remove(propertyName); 
     } 

     ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName)); 
    } 

    protected void OnErrorsChanged(string propName) 
    { 
     ErrorsChanged(this, new DataErrorsChangedEventArgs(propName)); 
    } 
}` 

Und es funktioniert gut, aber erst, nachdem ich Eigenschaften in area per meinem Fenster ändern. Das Hauptproblem ist, dass Benutzer nicht in der Lage sein, Modell zu speichern, ohne erforderliche Felder zu füllen, aber wenn Windows laden Schaltfläche Speichern (die Befehl verwendet) verfügbar, wegen der Validierung nicht ausgeführt wird.

Hier ist XAML:

<Window x:Class="ValidationTests.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:ValidationTests" 
    xmlns:rules="clr-namespace:ValidationTests.Rules" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded"> 
<Window.Resources> 
    <Style x:Key="TextBoxError" TargetType="{x:Type TextBox}"> 
     <Setter Property="Validation.ErrorTemplate"> 
      <Setter.Value> 
       <ControlTemplate x:Name="TextErrorTemplate"> 
        <DockPanel LastChildFill="True"> 
         <AdornedElementPlaceholder> 
          <Border BorderBrush="Red" BorderThickness="2"/> 
         </AdornedElementPlaceholder> 
        </DockPanel> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</Window.Resources> 
<Grid> 
    <StackPanel> 
     <Label>Artist</Label> 
     <TextBox Style="{StaticResource TextBoxError}" Text="{Binding Artist, 
      ValidatesOnNotifyDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"> 
     </TextBox> 
     <Label>Title</Label> 
     <TextBox Style="{StaticResource TextBoxError}" Text="{Binding Title, 
      ValidatesOnNotifyDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox> 
     <Label>Lyrics</Label> 
     <TextBox Style="{StaticResource TextBoxError}" Text="{Binding Lyrics, 
      ValidatesOnDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox> 
     <Button Content="Add" Command="{Binding AddCommand}"></Button> 
    </StackPanel> 
</Grid> 

Ich frage mich, wie ich dieses Problem beheben kann ...

Antwort

0

Ich frage mich, wie ich dieses Problem beheben kann ...

Sie müssen die eigentliche Validierung im Voraus durchführen.

Rufen Sie die ValidateProperty Methode für alle Objekte im Konstruktor Ihrer EditableSong Klasse die Dictionary und erhöhen die ErrorsChanged Ereignis zu füllen:

public EditableSong() 
{ 
    addcommand = new CommandRelay(Add, CanAdd); 

    ValidateProperty(nameof(Title), title); 
    ValidateProperty(nameof(Lyrics), lyrics); 
    ValidateProperty(nameof(Artist), artist); 
} 
+0

Dank half es! – AfDs

Verwandte Themen