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.04k stars 1.12k forks source link

[BUG] POCOObservableForProperty warnings with ReactiveUI.WinForms #2669

Open ivar-rummelhoff opened 3 years ago

ivar-rummelhoff commented 3 years ago

I started getting these warnings after upgrading a project to ReactiveUI.WinForms v13.1.1 from an old version. This also happens when upgrading ReactiveUI.Winforms.Samples.Bindings in https://github.com/Asesjix/ReactiveUI.Winforms.Samples (linked to from https://www.reactiveui.net/docs/resources/samples):

POCOObservableForProperty: The class ReactiveUI.Winforms.Samples.Bindings.Views.MainView property ViewModel is a POCO type and won't send change notifications, WhenAny will only return a single value!
POCOObservableForProperty: The class ReactiveUI.Winforms.Samples.Bindings.Views.MainView property tbInputOne is a POCO type and won't send change notifications, WhenAny will only return a single value!
POCOObservableForProperty: The class ReactiveUI.Winforms.Samples.Bindings.Views.MainView property lOutputOne is a POCO type and won't send change notifications, WhenAny will only return a single value!
POCOObservableForProperty: The class ReactiveUI.Winforms.Samples.Bindings.Views.MainView property dtpInputTwo is a POCO type and won't send change notifications, WhenAny will only return a single value!
POCOObservableForProperty: The class ReactiveUI.Winforms.Samples.Bindings.Views.MainView property lOutputTwo is a POCO type and won't send change notifications, WhenAny will only return a single value!

These are the statements that result in the warnings above, written to the console when debugging:

this.WhenActivated(d =>
{
    // One way bind from viewmodel to view
    d(this.OneWayBind(ViewModel, vm => vm.ApplicationTitle, v => v.Text));

    // Two way bind for input (textbox) and one way bind for output (label)
    d(this.Bind(ViewModel, vm => vm.ValueOne, v => v.tbInputOne.Text));
    d(this.OneWayBind(ViewModel, vm => vm.ValueOne, v => v.lOutputOne.Text));

    // Two way bind for input (textbox) with convert and one way bind for output (label)
    d(this.Bind(ViewModel, vm => vm.ValueTwo, v => v.dtpInputTwo.Value, t => DateTime.FromFileTime(t), dt => dt.ToFileTime()));
    d(this.OneWayBind(ViewModel, vm => vm.ValueTwo, v => v.lOutputTwo.Text));
});

Unless there is a better way to set up such bindings now, I believe these warnings should be silenced.

Environment

RLittlesII commented 3 years ago

Does this resolve your issue?

https://github.com/reactiveui/ReactiveUI/issues/2037#issuecomment-493662223

ivar-rummelhoff commented 3 years ago

I am not 100% sure what you suggest, but setting

RxApp.SuppressViewCommandBindingMessage = true;

does not appear to have any effect on these warnings in ReactiveUI.Winforms 13.2.2.

zhengyong1023 commented 3 years ago

I also have this problem. How can I solve it。 I try to add this line "RxApp.SuppressViewCommandBindingMessage = true;" but it's nothing has changed

tomasfil commented 2 years ago

This setting still doesnt work.

I did set the supress to true, but I am still getting:

2021-11-04 08:46:47.2027|WARN|ReactiveUI.POCOObservableForProperty|The class KardexTerminal_PDA_WPF.MainWindow property ViewModelViewHost_SerialInput is a POCO type and won't send change notifications, WhenAny will only return a single value!
2021-11-04 08:46:47.2249|WARN|ReactiveUI.POCOObservableForProperty|The class KardexTerminal_PDA_WPF.MainWindow property ViewModelViewHost_ReorderLogs is a POCO type and won't send change notifications, WhenAny will only return a single value!
2021-11-04 08:46:47.2416|WARN|ReactiveUI.POCOObservableForProperty|The class Wms.Wpf.Services.ShutdownService property ShutdownCommand is a POCO type and won't send change notifications, WhenAny will only return a single value!
Awsmolak commented 2 years ago

This problem still exists for WPF. And it dirties up the logs significantly. If you are using Serilog, I recommend Serilog.Expressions, makes it really easy to filter them out at that level.

drepamig commented 1 year ago

This problem still exists for WPF. And it dirties up the logs significantly. If you are using Serilog, I recommend Serilog.Expressions, makes it really easy to filter them out at that level.

This worked for me since I couldn't get messages to stop by setting RxApp.SuppressViewCommandBindingMessage = true

Since how to do this didn't immediately click for me, for anyone else in the same boat, these are the steps that worked for me:

  1. Add the packages Splat.Serilog and Serilog.Expressions
  2. Configure Serilog to exclude the message:
         Log.Logger = new LoggerConfiguration()
                .Filter.ByExcluding(x=> x.Exception?.Message.StartsWith("POCOObservableForProperty: The class") == true)
                .CreateLogger();
  3. Tell Splat to use that Serilog instance: Locator.CurrentMutable.UseSerilogFullLogger(Log.Logger)
  4. Enjoy cleaner logs and debug outputs!
jbuckmccready commented 1 year ago

I ran into this in WPF and this warning message is very confusing because all of the bindings work correctly despite the warning suggesting otherwise. And the documentation suggests binding in a way that produces this exact warning (see docs here: https://www.reactiveui.net/docs/handbook/data-binding/windows-presentation-foundation).

I eliminated the warnings by overriding the property resolver, see also this question on stackoverflow: https://stackoverflow.com/questions/30352447/using-reactiveuis-bindto-to-update-a-xaml-property-generates-a-warning

Using the following code eliminates the warnings and all of the bindings continue to work:

public class CustomPropertyResolver : ICreatesObservableForProperty
{
    public int GetAffinityForObject(Type type, string propertyName, bool beforeChanged = false) => 1;

    public IObservable<IObservedChange<object, object>> GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false)
    {
        return Observable.Return(new ObservedChange<object, object>(sender, expression, default), RxApp.MainThreadScheduler)
            .Concat(Observable.Never<IObservedChange<object, object>>());
    }
}

Then in main/app startup before creating the bindings:

Locator.CurrentMutable.Register(() => new CustomPropertyResolver(), typeof(ICreatesObservableForProperty));

The warning message comes from this implementation here (which is what I based the code above on): https://github.com/reactiveui/ReactiveUI/blob/main/src/ReactiveUI/ObservableForProperty/POCOObservableForProperty.cs

The bug seems to be the bindings always falling through to that POCOObservableForProperty class.

Windows Presentation Foundation
Stack Overflow
Using ReactiveUI's BindTo() to update a XAML property generates a warning
I'm trying to update a property of an element in the XAML of a view: this.WhenAnyValue(x => x.ViewModel.IsEnabled).BindTo(this, x => x.MyButton.IsEnabled); This works as expected, however, it
GitHub
ReactiveUI/POCOObservableForProperty.cs at main · 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...