Reputation: 2128
I have a problem with ReactiveUI ObservableCollection. I am trying to update the UI based on a list that changes in a ReactiveObject, but for some reason my list change is not triggered and I am not sure what I am doing wrong.
There is a full repo here : https://github.com/SebiCiuca/ObserableCollection
App has a button, that when it's clicked calls a "RandomService" that removes items from a list and then adds a random number of items back into the list.
This list is an ObservableCollection that has a Subscribe on it, so I would like to see in my ViewModel that the list change happening in RandomService is triggering my ObservableCollection ModelList change.
Code below:
MainWindow
public partial class MainWindow : ReactiveWindow<MainWindowViewModel>
{
public MainWindow(MainWindowViewModel mainWindowViewModel)
{
InitializeComponent();
ViewModel = mainWindowViewModel;
DataContextChanged += (sender, args) => ViewModel = DataContext as MainWindowViewModel;
this.WhenActivated(cleanup =>
{
this.BindCommand(ViewModel, vm => vm.RandonListCommand, view => view.RandomButton).DisposeWith(cleanup);
});
}
}
MainWindowViewModel
public class MainWindowViewModel : ReactiveObject
{
private readonly IRandomService m_RandomService;
public ReactiveCommand<Unit, Unit> RandonListCommand { get; set; }
public MainWindowViewModel(IRandomService randomService)
{
m_RandomService = randomService;
RandonListCommand = ReactiveCommand.Create(() => { CallRandomService(); });
randomService.WhenAnyValue(rs => rs.ModelList).WhereNotNull().Subscribe(_ => TriggerUpdateUI());
}
private void CallRandomService()
{
Debug.WriteLine("Random is called");
var random = new Random();
var take = random.Next(1, 4);
Debug.WriteLine($"Take is {take}");
m_RandomService.UpdateList(take);
}
private void TriggerUpdateUI()
{
Debug.WriteLine("List changed");
foreach (var model in m_RandomService.ModelList)
{
Debug.WriteLine($"{model.Id} {model.Name}");
}
}
}
RandomService
public class RandomService : ReactiveObject, IRandomService
{
private List<RandomModel> _privateList;
public RandomService()
{
_privateList = new List<RandomModel>
{
new RandomModel { Id = 1, Name = "FirstRandom" },
new RandomModel { Id = 2, Name = "SecondRandom" },
new RandomModel { Id = 3, Name = "SecondRandom" },
new RandomModel { Id = 4, Name = "SecondRandom" }
};
_modelList = new();
}
private ObservableCollection<RandomModel> _modelList;
public ObservableCollection<RandomModel> ModelList
{
get => _modelList;
set => this.RaiseAndSetIfChanged(ref _modelList, value);
}
public void UpdateList(int take)
{
_modelList.Clear();
Debug.WriteLine($"ModelList count {_modelList.Count}");
var addToUI = _privateList.Take(take).ToList();
addToUI.Shuffle();
addToUI.ForEach(p => ModelList.Add(p));
Debug.WriteLine($"ModelList count {_modelList.Count}");
}
}
IRandomService
public interface IRandomService
{
ObservableCollection<RandomModel> ModelList { get; }
void UpdateList(int take);
}
From my point of view everything is correct if I read the definiton of ObservableCollection
"Represents a dynamic data collection that provides notifications when items get added or removed, or when the whole list is refreshed."
So my question is, why is my TriggerUpdateUI() never called. ( except at the start of the app when it's initialized).
Upvotes: 0
Views: 387
Reputation: 1664
randomService.WhenAnyValue(rs => rs.ModelList).WhereNotNull().Subscribe(_ => TriggerUpdateUI());
WhenAnyValue is just watching randomService for property change notifications for ModelList. You haven't set up anything to look for collection related changes.
From my point of view everything is correct if I read the definiton of ObservableCollection
"Represents a dynamic data collection that provides notifications when items get added or removed, or when the whole list is refreshed."
Your quote comes from the MS Docs on ObservableCollection. It is capable of producing collection change notifications, but you still need to setup something to react to them via ReactiveUI / DynamicData.
ReactiveUI Handbook - Collections
Upvotes: 2