reactiveui / ReactiveUI

An advanced, composable, functional reactive model-view-viewmodel framework for all .NET platforms that is inspired by functional reactive programming. ReactiveUI allows you to abstract mutable state away from your user interfaces, express the idea around a feature in one readable place and improve the testability of your application.
https://www.reactiveui.net
MIT License
8.08k stars 1.12k forks source link

[BUG] Two way binding is not working for NSTextfield #2412

Closed Dylan-DutchAndBold closed 4 years ago

Dylan-DutchAndBold commented 4 years ago

Describe the bug When two way binding a ViewModel to an NSTextField. The ViewModel is never updated. However the NSTextField is updated.

Steps To Reproduce

  1. Create a ReactiveViewController.
  2. Bind in the constructor
    this.Bind(ViewModel, vM => vM.ClientId, v => v.ClientIdTextField.StringValue);

Expected behavior

When changing the value of an NSTextField. The ViewModel's setter should be hit. Environment

Additional context It seems extremely similar to an earlier reported issue. https://github.com/reactiveui/ReactiveUI/issues/1603 . Which was fixed may 2018. However I have been reading the docs over and over. And however it is missing some details about Xamarin.Mac implementations. I think I got it right. I'll post the full ViewController code below.

// This file has been autogenerated from a class added in the UI designer.

using System;
using Moneybird.MacOs.ViewModels.Preferences;
using ReactiveUI;

namespace Moneybird.MacOs
{
    public partial class PreferencesViewController : ReactiveViewController<GeneralPreferencesViewModel>
    {
        public PreferencesViewController(IntPtr handle)
            : base(handle)
        {
            this.Bind(ViewModel, vM => vM.ClientId, v => v.ClientIdTextField.StringValue);
            this.Bind(ViewModel, vM => vM.ClientSecret, v => v.ClientSecretTextField.StringValue);
        }

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            ViewModel = RxApp.SuspensionHost.GetAppState<AppState>().GeneralPreferencesViewModel;
        }
    }
}
open-collective-bot[bot] commented 4 years ago

Hey @Dylan-DutchAndBold :wave:,

Thank you for opening an issue. We will get back to you as soon as we can. Also, check out our Open Collective and consider contributing financially.

https://opencollective.com/reactiveui

PS.: We offer priority support for all financial contributors. Don't forget to add priority label once you start contributing :smile:

ReactiveUI - Open Collective
An advanced, composable, functional reactive model-view-viewmodel framework for all .NET platforms!
Dylan-DutchAndBold commented 4 years ago

Using the WhenActivated method has fixed my issue now. I had read before it was good practise, but not mandatory (https://reactiveui.net/docs/handbook/data-binding/#types-of-bindings). But it seems it was mandatory in this case. I just didn't know how it was supposed to be implemented, but the project readme had an good example here https://github.com/reactiveui/ReactiveUI#binding-our-viewmodel-to-the-platform-specific-ui .

Data Binding
GitHub
reactiveui/ReactiveUI
An advanced, composable, functional reactive model-view-viewmodel framework for all .NET platforms that is inspired by functional reactive programming. ReactiveUI allows you to abstract mutable st...
RLittlesII commented 4 years ago

@Dylan-DutchAndBold Quick question I was going to ask. Sometimes (depending on how you construct objects) you have to manually set the BindingContext (ViewModel = new ViewModel()) in the view. Generally, I put a breakpoint in the ViewModel constructor to verify that it is getting hit when I run into issues like the one you described (literally did this before I saw the notification of this issue).

Dylan-DutchAndBold commented 4 years ago

@RLittlesII Thanks. I did put breakpoints on the getter and setter and noticed that only the getter was being hit, except for the setter being hit by Akavache once. I'm glad it is working now.

github-actions[bot] commented 2 years ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.