0

I'm using Reactive UI to bind Xamarin.Forms Picker SelectedItem to ViewModel property. (using Bind(), two ways binding). When I set the "Event" property in the ViewModel (after populating the SourceCache list) should update the selected item in the Picker, but only works on Android not in iOS.

I am using Reactive UI 9.16.6 and Xamarin Forms 3.6.0.344457 and Reactive.Fody

The Page:

namespace TicketPassManager.Forms.Pages.Dashboards.Invitations
{
    public class InvitationPage : ReactiveContentPage<InvitationPageViewModel>
    {
        Picker eventPicker;

        public InvitationPage()
        {
            eventPicker = new Picker
            {
                Title = "Evento",
                ItemDisplayBinding = new Binding(nameof(Event.Title)),
                TabIndex = 0
            };

            var stackLayout = new StackLayout
            {
                Children =
                {
                    eventPicker,
                }
            };

            Content = new ScrollView
            {
                Content = stackLayout
            };

                this.OneWayBind(ViewModel, vm => vm.EventList, v => v.eventPicker.ItemsSource).DisposeWith(disposables);
                this.Bind(ViewModel, vm => vm.Event, v => v.eventPicker.SelectedItem).DisposeWith(disposables);

                this.WhenAnyValue(v => v.ViewModel.LoadEventsCommand)
                    .Where(x => x != null)
                    .Select(x => Unit.Default)
                    .ObserveOn(RxApp.TaskpoolScheduler)
                    .InvokeCommand(ViewModel.LoadEventsCommand)
                    .DisposeWith(disposables);

                           });
        }
    }
}

The View Model:

namespace TicketPassManager.Forms.ViewModels.Dashboards.Invitations
{
    public class InvitationPageViewModel : ReactiveObject
    { 

        [Reactive] public Event Event { get; set; }

        public ReactiveCommand<Unit, EventCollection> LoadEventsCommand;

        public ObservableCollectionExtended<Event> EventList;
        private SourceCache<Event, long> SourceCacheEventList;

        public InvitationPageViewModel()
        {
            EventList = new ObservableCollectionExtended<Event>();

            SourceCacheEventList = new SourceCache<Event, long>(key => key.Id);
                var canExecuteLoadEventCommand =
                this.WhenAnyObservable(x => x.SourceCacheEventList.CountChanged)
                    .StartWith(0)
                    .Select(x => x == 0);

            LoadEventsCommand = ReactiveCommand.CreateFromObservable<Unit, EventCollection>(ExecuteLoadEvents, canExecuteLoadEventCommand);

            SourceCacheEventList
                .Connect()
                .DeferUntilLoaded()
                .Sort(SortExpressionComparer<Event>.Ascending(t => t.StartDateTime))
                .ObserveOn(RxApp.MainThreadScheduler)
                .Bind(EventList)
                .DisposeMany()
                .Subscribe();

                this.WhenAnyValue(x => x.Event)
                .Where(x => x != null)
                .InvokeCommand(LoadTicketTypesCommand);


            LoadEventsCommand.Subscribe(x =>
            {
                if (x.Any())
                {
                    SourceCacheEventList.Clear();
                    SourceCacheEventList.AddOrUpdate(x.Where(e => e.IsUpcoming));
                    Event = SourceCacheEventList.Items.OrderBy(e => e.StartDateTime).First();
                }
            });

        }

        private IObservable<EventCollection> ExecuteLoadEvents(Unit arg)
        {
            return Resolver.Resolve<TicketPassService>().GetEventsFromLocalAsync().ToObservable();
        }

    }
}
  • 1
    This is a fairly complex example you posted. You may need to cut it back to a https://stackoverflow.com/help/minimal-reproducible-example – Glenn Watson Jun 05 '19 at 00:09
  • Done! I removed not relevant code! – Juan Pablo Ibañez Jun 05 '19 at 00:17
  • @GlennWatson any clue? – Juan Pablo Ibañez Jun 16 '19 at 12:50
  • I seen similar issues before with lack of ObserveOn(RxApp.MainThreadScheduler) in the observable calls. Also commands have a scheduler you can pass into. I noticed that you observe on the TaskScheduler at times there so I would make sure that command any other observable dispatch onto the main thread. – Glenn Watson Jun 16 '19 at 13:29
  • Changing SourceCache and ObservableCollectionExtended to a simple List solved the problem, but if I wish to add or remove items on the fly probably don't work with List @GlennWatson, any other clue? Everything is working on MainThread now. – Juan Pablo Ibañez Jun 23 '19 at 23:25

0 Answers0