Hallo,
ich nutze im WPF DataGrid das SourceUpdated Event um Änderungen
am Benutzer (PMUser) zu validieren:
<DataGrid...
Style="{Controls:StaticResource MahApps.Styles.DataGrid.Azure}"
SelectedItem="{Binding SelectedItem}"
ItemsSource="{Binding Path=PM_UserList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SourceUpdated">
<i:InvokeCommandAction Command="{Binding DataSourceUpdatedCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Username, Mode=TwoWay, UpdateSourceTrigger=LostFocus, NotifyOnSourceUpdated=True}" Width="100"/>
<DataGridComboBoxColumn Header="Level" ItemsSource="{Binding Source={StaticResource UserRoleProvider}}" SelectedItemBinding="..."/>
<DataGridTextColumn Header="HasValidationError" Binding="{Binding HasInvalidData, Mode=OneWay}"/>
PMUser implementiert hier INotifyPropertyChanged wie folgt:
public class MySQLNotifier
{
public event PropertyChangedEventHandler PropertyChanged;
public event PropertyChangedEventHandler SQLChangedDataPropertyChanged;
public void OnPropertyChanged(string prop)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
public void OnSQLDataPropertyChanged(string prop)
{
if (IsInitialized)
HasChanged = true;
SQLChangedDataPropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
}
public class PMUser : MySQLNotifier, IPMValidation
{
private ObservableCollection<App_ErrorEnum> _ValidationErrors = new ObservableCollection<App_ErrorEnum>();
public ObservableCollection<App_ErrorEnum> ValidationErrors
{
get { return _ValidationErrors; }
set
{
_ValidationErrors = value;
OnPropertyChanged(nameof(ValidationErrors));
}
}
private bool _HasInvalidData = false;
public bool HasInvalidData
{
get { return _HasInvalidData; }
set
{
_HasInvalidData = value;
OnPropertyChanged("HasInvalidData");
}
}
private int _ValidationErrorCount = 0;
public int ValidationErrorCount
{
get { return _ValidationErrorCount; }
set
{
_ValidationErrorCount = value;
OnPropertyChanged("ValidationErrorCount");
}
}
private string _Username;
public string Username
{
get { return _Username; }
set
{
_Username = value;
OnSQLDataPropertyChanged("Username");
OnSQLDataPropertyChanged("IsCurrentUser");
}
}
private UserRoleEnum _Userlevel;
public UserRoleEnum Userlevel
{
get { return _Userlevel; }
set
{
_Userlevel = value;
OnSQLDataPropertyChanged("Userlevel");
}
}
...
public void
Validation_Add(App_ErrorEnum newError)
{
ValidationErrors.Add(newError);
}
public void
Validate()
{
/* clear old validation */
ValidationErrors.Clear();
/* check empty username */
if (string.IsNullOrEmpty(Username))
Validation_Add(App_ErrorEnum.EmptyUsername);
else
{
PMUser _found = SQLConnector.Get_PMUser(Username);
if (_found != null)
{
/* new user: username exist */
/* old user: new username exist */
if (IsNew || SQL_ID != _found.SQL_ID)
Validation_Add(App_ErrorEnum.UsernameAlreadyExist);
}
}
...
HasInvalidData = ValidationErrors.Count > 0;
ValidationErrorCount = ValidationErrors.Count;
ValidationString = string.Empty;
foreach (var item in ValidationErrors)
ValidationString += item + " ";
}
PMUser.Validate() wird nun über das erwähnte SourceUpdatedEvent im UserViewModel ausgeführt:
private void On_DataSourceChanged(DataTransferEventArgs args)
{
var changedUser = ((FrameworkElement)args.OriginalSource).DataContext as PMUser;
if (changedUser == null)
return;
/* validate user data */
changedUser.Validate();
[breakPoint]
}
Über den BreakPoint erkenne ich, dass die Validierung erfolgt ist sobald bspw. username = string.Empty:
[changedUser ValidationErrorCount = 1, ValidationErrors = Count = 1, HasInvalidData = true, ValidationString = "EmptyUsername "]
Das Problem:
Im DataGrid werden diese Columns nicht aktualisiert (zeigen 0, bzw. false), obwohl das Model die korrekten Werte enthält.
<DataGridTextColumn Header="HasValidationError" Binding="{Binding HasInvalidData, Mode=OneWay}"/>
<DataGridTextColumn Header="ValidationErrorCount" Binding="{Binding ValidationErrorCount, Mode=OneWay}"/>
Diese DEBUG-Column zeigt hierbei immer den korrekten Zähler an Validation - Errors.
<DataGridTextColumn Header="ECount" Binding="{Binding ValidationErrors.Count, Mode=OneWay}"/>
Was übersehe ich?
Du hast vergessen, das INotifyPropertyChanged-Interface zu implementieren. Siehe dazu diese Anleitung: [Artikel] MVVM und DataBinding
Weeks of programming can save you hours of planning
Habs, Danke dir.
In C# bzw. .NET reicht es nicht nur die Methoden eines Interfaces zu implementieren.
Man muss das Interface an der Klasse bekannt machen.
Siehe interface – C#-Referenz
Edit: durch Dein Edit obsolete.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code