使用 ReactiveUI/DynamicData,我在SelectedItem更新ItemSource. 我使用 aSourceList<T>来保存可变集合以及 Connect/Bind/Subscribe 来更新ReadOnlyObservableCollection绑定到ComboBox.ItemSource.
在ComboBox视图中是这样绑定的:
this.OneWayBind(ViewModel, vm => vm.EventYearsList, v => v.EventYearsComboBox.ItemsSource).DisposeWith(d);
this.Bind(ViewModel, vm => vm.SelectedEventYear, v => v.EventYearsComboBox.SelectedItem).DisposeWith(d);
在 ViewModel 中,我定义了 aReactiveCommand来更新SourceList, aSourceList保存从服务层返回的数据, aReadOnlyObservableCollection绑定到ComboBox.ItemSource,以及一个属性来保存SelectedItem.
public ReactiveCommand<Unit, Unit> GetEventYearsListCommand { get; }
private readonly SourceList<short> _eventYearsSourceList = new SourceList<short>();
private readonly ReadOnlyObservableCollection<short> _eventYearsList;
public ReadOnlyObservableCollection<short> EventYearsList => _eventYearsList;
private short? _selectedEventYear;
public short? SelectedEventYear
{
get => _selectedEventYear;
set => this.RaiseAndSetIfChanged(ref _selectedEventYear, value);
}
在 ViewModel 的构造函数中,我设置了订阅:
GetEventYearsListCommand = ReactiveCommand.CreateFromTask(ExecuteGetEventYearsListCommand);
GetEventYearsListCommand.ThrownExceptions.Subscribe(ex => Trace.WriteLine(ex.ToString()));
_eventYearsSourceList
.Connect()
.ObserveOn(RxApp.MainThreadScheduler)
.Bind(out _eventYearsList)
.Subscribe();
// when a series is selected, this fires off the command to update the event years
this.WhenAny(x => x.SelectedSeries, _ => Unit.Default)
.ObserveOn(RxApp.MainThreadScheduler)
.InvokeCommand(GetEventYearsListCommand);
请注意,当用户在另一个ListBox...
最后,更新命令SourceList如下所示:
private async Task ExecuteGetEventYearsListCommand()
{
var eventYearsList = new List<short>();
if (SelectedSeries != null)
{
eventYearsList = await seriesApi.QueryEventYears(SelectedSeries.OrgSeriesPath);
}
_eventYearsSourceList.Edit(list =>
{
list.Clear();
if (eventYearsList != null) list.AddRange(eventYearsList);
});
// This trace shows the correct number of items in the list
Trace.WriteLine($"_eventYearsSourceList count = {_eventYearsSourceList.Count}");
// But here, I don't get the right count, EventYearsList has not been updated yet!!!
Trace.WriteLine($"EventYearsList count = {EventYearsList.Count}");
// and this check isn't even valid, because EventYearsList hasn't been updated...
if (EventYearsList?.Count > 0)
{
SelectedEventYear = EventYearsList.First();
}
}
所以直接看上面的命令...我已经更新了SourceList,但ReadOnlyObservableCollection还没有更新...它仍然显示SourceList我更新之前的内容。
第一个问题是,我什至没有从新更新的列表中获得第一项,因为它还没有更新。
第二个问题是,即使我现在设置所选项目,当 EventYearsList 最终更新时,该选择也会丢失。由于所选项目的双向绑定(我假设),SelectedEventYear在 EventYearsList 最终更新后设置为 null 。因此,即使我现在可以设置所选项目,它也会被覆盖。(我已通过在 SelectedEventYear 属性设置器上设置断点来确认此行为)
要么我做错了什么......要么我需要找到一种方法来(单独)连接到一些东西,告诉我什么时候底层的来源发生了ReadOnlyObservableCollection变化。
所以回到最初的问题......我如何SelectedItem将更新后设置为ItemSource?