Relative Bindings Fail with CompileBindings Enabled (ReactiveUI/MVVM)
See original GitHub issueDescribe the bug
I’m experiencing an issue with Avalonia 11.0.0-rc1.1 where relative bindings fail to compile when CompileBindings
is enabled. I’ve tried three different syntaxes for binding to the parent window’s ViewModel, all of which yield the same error:
{Binding ViewModel.TestMethodCommand, RelativeSource={RelativeSource AncestorType={x:Type views:MainWindow}}}
{Binding #Window.ViewModel.TestMethodCommand}
{Binding $parent[views:MainWindow].ViewModel.TestMethodCommand}
To Reproduce Steps to reproduce the behavior:
- Create a new project with the Avalonia MVVM template
- Make sure that the
MainWindow
class derives fromReactiveWindow<MainWindowViewModel>
, and notWindow
- Set
CompiledBindings
toTrue
on the window - Implement a test command in
MainWindowViewModel
- Place a button on the window, bind it to the test command via any of the three methods mentioned above
- Try to compile the application
- The following exception is thrown while compiling the bindings:
MainWindow.axaml(18, 17): [AVLN:0004] Internal compiler error while emitting node Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.XamlIlBindingPathHelper+XamlIlBindingPathNode:
System.NullReferenceException: Object reference not set to an instance of an object.
at Mono.Cecil.ImportGenericContext.TypeParameter(String type, Int32 position)
at Mono.Cecil.DefaultMetadataImporter.ImportTypeSpecification(TypeReference type, ImportGenericContext context)
...
Expected behavior The program should compile successfully.
Desktop:
- OS: Windows 11 22H2
- Version 11.0.0-rc1.1 and 11.0.0-preview8
Additional context
The error only occurs when CompileBindings
is enabled. If I disable it, the code compiles and the binding works as expected. The error in question is an internal compiler error with a NullReferenceException
.
The issue might be related to #10489 and #10486.
Use case
The obvious answer would be to simply not use relative bindings and bind to the ViewModel directly (assuming that x:DataType
is set on the control/window) which would work as expected regardless of the state of CompiledBindings
. However in my specific use case, I was trying to bind to a command in a custom control’s ViewModel from within the ItemTemplate
of a ListBox
(a simple “delete this row” button), where I had to use relative bindings to reach my ViewModel.
This is not a critical bug in my case since I can just disable CompiledBindings
for the time being, but I do enjoy the benefits of the function such as additional IntelliSense and syntax highlighting in the axaml editor when it’s enabled, so I would consider it an annoying bug.
Issue Analytics
- State:
- Created 4 months ago
- Comments:5 (1 by maintainers)
Top GitHub Comments
I was having the same issue, and found that you can instead use ReflectionBinding for those specific cases. e.g. Instead of Command=“{Binding ElementName=X, Path=DataContext.DoYCommand}” do Command=“{ReflectionBinding ElementName=X, Path=DataContext.DoYCommand}”
This turns off compiled bindings for this binding only.
While I think in ReactiveWindow it should work without, one can also cast in the C# like cast style inside a binding. e.g.
{Binding $parent[Window].((vm:MyViewModel).DataContext).MyCommand }