Laden...

DataGridCell | Value wird nicht aktualisiert

Erstellt von jbrown vor 2 Jahren Letzter Beitrag vor 2 Jahren 297 Views
J
jbrown Themenstarter:in
18 Beiträge seit 2021
vor 2 Jahren
DataGridCell | Value wird nicht aktualisiert

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?

5.658 Beiträge seit 2006
vor 2 Jahren

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

J
jbrown Themenstarter:in
18 Beiträge seit 2021
vor 2 Jahren

Habs, Danke dir.

16.835 Beiträge seit 2008
vor 2 Jahren

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.