'Reactive UI - Tracking Changed Properties
Consider the below code. I'm trying to track the property changed event of the Student object in the view model. The Student class implements the INotifyPropertyChanged interface. The changed property of the Student class and its value needs to be accessed in the ViewModel. How this can be achieved?
//ViewModel
public class StudentViewModel: ReactiveObject
{
//Model Object
private Student? _student;
public Student? Student
{
get => _student;
set => this.RaiseAndSetIfChanged(ref _student, value);
}
public StudentViewModel()
{
.WhenAnyValue(x => x.Student)
// How to get the changed property and the value of the propertied in Studen class
.Subscribe(x => OnModelPropertyChanged(x.propertyName, x.propertyValue));
}
OnModelPropertyChanged(string propertyName, object PropertyValue)
{
}
}
//Model
public class Student : INotifyPropertyChanged
{
public int Id {get;set;}
public int StudentName {get;set;}
}
Note: I can access the changed property by adding the below code, but not the value.
.WhenAnyValue(x => x.Student)
.Select(x => x == null ? Observable.Never<EventPattern<object>>() : Observable.FromEventPattern(x, nameof(x.PropertyChanged)))
.Switch()
.Subscribe(x => OnModelPropertyChanged(x));
Solution 1:[1]
First you have to distinguish between using WhenAny on the student object like u did:
WhenAnyValue(x => x.Student) and WhenAny on the student properties like WhenAnyValue(x => x.Student.StudentName) because they are 2 separated things.
First one, let you know if student instance in the ViewModel changes, the second tells you if studen's property changed. As far as i know, you cant apply WhenAny to check if any of the object's properties are changed.
Solution for you is to directly subscribe PropertyChanged event of the object that implements INotifyPropertyChanged - Student.
public Vm()
{
Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
handler => _student.PropertyChanged += handler,
handler => _student.PropertyChanged -= handler
)
.Select(n =>
{
var student = (Student)n.Sender;
var property = typeof(Student).GetProperty(n.EventArgs.PropertyName);
var propertyValue = property.GetValue(student);
return propertyValue;
})
.Subscribe();
}
Because the event gives you a property name, you're able to get any property from the object.
You can also do something like
_student.WhenAnyPropertyChanged(nameof(Student.Id), nameof(Student.Name))
.Do(student => { })
.Subscribe();
but you will mis which property changed and of course you have to list all of the properties to watch.
Hope this helps.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
