Пользовательский интерфейс не обновляется после выполнения ReactiveCommand

#c# #wpf #async-await #reactiveui

#c# #wpf #асинхронный-ожидание #reactiveui

Вопрос:

Все, что я хочу, это получить некоторые данные из сервиса, а затем показать их с помощью DataGrid в новом окне после нажатия кнопки. Прежде всего, я должен упомянуть, что загрузка данных должна размещаться в новом окне, а не в его владельце.

Проблема в том, что любой подход, связанный с трудоемкой задачей с помощью ReactiveCommands (либо CreateFromTask, либо CreateFromObservable), не приносит мне никакого результата. Я успешно получаю свои данные из службы, затем свойство Data также успешно обновляется, НО я не вижу ничего, кроме имен столбцов DataGrid. Если я заменю LoadDataCommand на just Data = new List<...>() { new ..., new...} (hardcoded), все работает нормально, поэтому проблема заключается в загрузке данных и передаче этих данных в пользовательский интерфейс, а не в привязке, как я привык думать.

К сожалению, я совсем новичок в ReactiveUI, и я прочитал несколько статей в reactiveui.net/docs и ответы других здесь, прежде чем спрашивать, но ни один из них мне не помогает, хотя кажется, что я применяю те же подходы.

Владелец:

 var window = new PaymentsDetailingView(request)
            {
                WindowStartupLocation = WindowStartupLocation.CenterScreen
            };
            window.ShowDialog();
 

Затем я начинаю загружать данные в конструктор следующим образом:

xaml.cs

 public PaymentsDetailingView(CounterpartyPaymentRequest request)
        {
            ViewModel = new PaymentsDetailingViewModel(request);
            InitializeComponent();

            this.WhenActivated(disposables =>
            { // some bindings (to DataGrid too)

                this.WhenAnyValue(x => x.ViewModel.LoadDataCommand).SelectMany(x => x.Execute()).Subscribe()
                    .DisposeWith(disposables);
            });     
 

ViewModel:

 public List<PaymentsDetailingData> Data
        {
            get => _data;
            set =>  this.RaiseAndSetIfChanged(ref _data, value);
        }       

        public ReactiveCommand<Unit, List<PaymentDetailingResponseModel>> LoadDataCommand { get; set; } 
        
        public PaymentsDetailingViewModel(CounterpartyPaymentRequest request)
        {
            Request = request;

            //LoadDataCommand = ReactiveCommand.CreateFromTask(GetAndShowPaymentDetailedDataAsync);

            LoadDataCommand =
                ReactiveCommand.CreateFromObservable(() => Observable.StartAsync(GetAndShowPaymentDetailedDataAsync, RxApp.MainThreadScheduler));

                //LoadDataCommand = ReactiveCommand.CreateFromObservable(
                //  () =>
                //      Observable.FromAsync(GetAndShowPaymentDetailedDataAsync));

            LoadDataCommand/*.ObserveOn(RxApp.TaskpoolScheduler)*/
                .Subscribe(x => Data = x.AddTotalRow().ToUiModels());

            LoadDataCommand.ThrownExceptions.Subscribe(e => this.Log().Error(e));
            LoadDataCommand.IsExecuting.ToProperty(this, x => x.IsLoading, out _isLoading);
        }       

        private async Task<List<PaymentDetailingResponseModel>> GetAndShowPaymentDetailedDataAsync()
        { 
            var arService = Locator.Current.GetService<IAnalyticalReportingService>();
            var results = await arService.ExecuteDetailedCounterpartyPaymentInfo(Request, new CancellationToken());

            return results;
        }
    }
 

Комментарии:

1. Вероятно, сначала стоит проверить, что привязки на стороне представления OneWay , например {Binding Value, Mode=OneWay} . Такие платформы, как UWP и некоторые элементы управления WPF, как правило, используют OneTime привязки по умолчанию. Однако это не применимо к типобезопасным привязкам ReactiveUI. Также стоит добавить .ObserveOn(RxApp.MainThreadScheduler) (не TaskPoolScheduler ) прямо перед вызовом .Subscribe на LoadDataCommand . .ObserveOn(RxApp.MainThreadScheduler) гарантирует, что внутренний код Subscribe выполняется в основном потоке.

2. Если ничего из этого не помогает, вероятно, стоит сделать минимальную проверку и перейти к ReactiveUI Slack ( reactiveui канал поддержки).