Avalonia icon indicating copy to clipboard operation
Avalonia copied to clipboard

OneWayToSource bindings don't work for read-only direct properties

Open timunie opened this issue 5 months ago • 4 comments

          @grokys Found a bug: after the refactor, OneWayToSource bindings don't work for read-only direct properties, i.e.:
<Border>
  <Border.ContextFlyout>
    <Flyout IsOpen="{CompiledBinding IsOpen, Mode=OneWayToSource}">
      <Border  />
    </Flyout>
  </Border.ContextFlyout>
</Border>
Unhandled exception. System.ArgumentException: The property IsOpen is readonly.
 at Avalonia.DirectProperty`2.InvokeSetter(AvaloniaObject instance, BindingValue`1 value) in /Users/bartek/Programowanie/temp/Avalonia/src/Avalonia.Base/DirectProperty.cs:line 119
 at Avalonia.AvaloniaObject.SetDirectValueUnchecked[T](DirectPropertyBase`1 property, BindingValue`1 value) in /Users/bartek/Programowanie/temp/Avalonia/src/Avalonia.Base/AvaloniaObject.cs:line 819
 at Avalonia.DirectPropertyBase`1.RouteSetDirectValueUnchecked(AvaloniaObject o, Object value) in /Users/bartek/Programowanie/temp/Avalonia/src/Avalonia.Base/DirectPropertyBase.cs:line 164
 at Avalonia.PropertyStore.ValueStore.Avalonia.Data.Core.IBindingExpressionSink.OnChanged(UntypedBindingExpressionBase instance, Boolean hasValueChanged, Boolean hasErrorChanged, Object value, BindingError error) in /Users/bartek/Programowanie/temp/Avalonia/src/Avalonia.Base/PropertyStore/ValueStore.cs:line 765
 at Avalonia.Data.Core.UntypedBindingExpressionBase.PublishValue(Object value, BindingError error) in /Users/bartek/Programowanie/temp/Avalonia/src/Avalonia.Base/Data/Core/UntypedBindingExpressionBase.cs:line 429
 at Avalonia.Data.Core.BindingExpression.StartCore() in /Users/bartek/Programowanie/temp/Avalonia/src/Avalonia.Base/Data/Core/BindingExpression.cs:line 379
 at Avalonia.Data.Core.UntypedBindingExpressionBase.Start(Boolean produceValue) in /Users/bartek/Programowanie/temp/Avalonia/src/Avalonia.Base/Data/Core/UntypedBindingExpressionBase.cs:line 473
 at Avalonia.Data.Core.UntypedBindingExpressionBase.AttachAndStart(IBindingExpressionSink subscriber, AvaloniaObject target, AvaloniaProperty targetProperty, BindingPriority priority) in /Users/bartek/Programowanie/temp/Avalonia/src/Avalonia.Base/Data/Core/UntypedBindingExpressionBase.cs:line 208
 at Avalonia.PropertyStore.ValueStore.AddBinding(AvaloniaProperty property, UntypedBindingExpressionBase source) in /Users/bartek/Programowanie/temp/Avalonia/src/Avalonia.Base/PropertyStore/ValueStore.cs:line 55
 at Avalonia.AvaloniaObject.Bind(AvaloniaProperty property, IBinding binding, Object anchor) in /Users/bartek/Programowanie/temp/Avalonia/src/Avalonia.Base/AvaloniaObject.cs:line 635
 at Avalonia.AvaloniaObject.Bind(AvaloniaProperty property, IBinding binding) in /Users/bartek/Programowanie/temp/Avalonia/src/Avalonia.Base/AvaloniaObject.cs:line 421
 at Avalonia.AvaloniaObjectExtensions.Bind(AvaloniaObject target, AvaloniaProperty property, IBinding binding, Object anchor) in /Users/bartek/Programowanie/temp/Avalonia/src/Avalonia.Base/AvaloniaObjectExtensions.cs:line 251
 at ControlCatalog.MainWindow.!XamlIlPopulate(IServiceProvider, MainWindow) in /Users/bartek/Programowanie/temp/Avalonia/samples/ControlCatalog/MainWindow.xaml:line 42
 at ControlCatalog.MainWindow.!XamlIlPopulateTrampoline(MainWindow)
 at ControlCatalog.MainWindow.InitializeComponent() in /Users/bartek/Programowanie/temp/Avalonia/samples/ControlCatalog/MainWindow.xaml.cs:line 32
 at ControlCatalog.MainWindow..ctor() in /Users/bartek/Programowanie/temp/Avalonia/samples/ControlCatalog/MainWindow.xaml.cs:line 25
 at ControlCatalog.App.SetCatalogThemes(CatalogTheme theme) in /Users/bartek/Programowanie/temp/Avalonia/samples/ControlCatalog/App.xaml.cs:line 99
 at ControlCatalog.App.Initialize() in /Users/bartek/Programowanie/temp/Avalonia/samples/ControlCatalog/App.xaml.cs:line 40

Originally posted by @BAndysc in https://github.com/AvaloniaUI/Avalonia/issues/13970#issuecomment-1920429841

timunie avatar Feb 01 '24 12:02 timunie

I wasn't sure whether I should create an issue for this if the change is not live on the stable version, but actually it makes sense to do it since the PR is already merged 😅 thanks

BAndysc avatar Feb 01 '24 12:02 BAndysc

that is what I think nightly is for.

timunie avatar Feb 01 '24 12:02 timunie

cc @grokys

maxkatz6 avatar Feb 01 '24 20:02 maxkatz6

This one is relatively big bug, as OneWayToSource is commonly used on read-only properties

maxkatz6 avatar Feb 01 '24 20:02 maxkatz6

I don't see how we can fix this without using some heuristics to find the underlying field of a read-only property. I would instead prefer to keep the behavior as is because I don't think one should mutate a read-only property in XAML.

hez2010 avatar Mar 14 '24 05:03 hez2010

@hez2010 OneWayToSource means the control reports it's state to the VM but not the other way around. That is a totally valid use case. You can bind to IsEffectivelyEnabled for example or ItemsCount or whatever readonly property.

timunie avatar Mar 14 '24 06:03 timunie

This should have been fixed by https://github.com/AvaloniaUI/Avalonia/pull/14513 I think?

grokys avatar Mar 14 '24 15:03 grokys

This should have been fixed by #14513 I think?

Yes and It works perfectly fine, this issue was opened before the fix :)

BAndysc avatar Mar 14 '24 18:03 BAndysc