Skip to content

System.StackOverflowException when using OneWayToSource binding #4438

@LtDetFrankDrebin

Description

@LtDetFrankDrebin

When I use OneWayToSource binding from a control to ViewModel I get wrong behavior:

  1. StackOverflowException happens.
  2. In spite of OneWayToSource binding control tries to read from Property in ViewModel.

Example 1:
View:

<Window xmlns="https://github.com/avaloniaui"
				xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
				xmlns:vm="clr-namespace:Tests.ViewModels;assembly=Tests"
				xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
				xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
				mc:Ignorable="d"
				d:DesignWidth="800" d:DesignHeight="450"
				x:Class="Tests.Views.MainWindowView"
				Icon="/Assets/avalonia-logo.ico"
				Title="Tests">

	<Design.DataContext>
		<vm:MainWindowViewModel/>
	</Design.DataContext>

	<ItemsControl Items="{Binding Items}">
		<ItemsControl.ItemTemplate>
			<DataTemplate>
				<StackPanel>
					<TextBlock Bounds="{Binding Bounds, Mode=OneWayToSource}" />
				</StackPanel>
			</DataTemplate>
		</ItemsControl.ItemTemplate>
	</ItemsControl>

</Window>

ViewModel:

using Avalonia;
using ReactiveUI;
using System.Collections.Generic;

namespace Tests.ViewModels
{
	public class MainWindowViewModel : ReactiveObject
	{
		public class Item : ReactiveObject
		{
			Rect _bounds;
			public Rect Bounds
			{
				get => _bounds;
				set => this.RaiseAndSetIfChanged( ref _bounds, value );
			}
		}

		List<Item> _items = new List<Item> { new Item(), new Item(), };
		public List<Item> Items
		{
			get => _items;
			set => this.RaiseAndSetIfChanged( ref _items, value );
		}
	}
}

Result:
After executing I get infinity loop in set => this.RaiseAndSetIfChanged( ref _bounds, value );.

Example 2:
View:

<Window xmlns="https://github.com/avaloniaui"
				xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
				xmlns:vm="clr-namespace:Tests.ViewModels;assembly=Tests"
				xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
				xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
				mc:Ignorable="d"
				d:DesignWidth="800" d:DesignHeight="450"
				x:Class="Tests.Views.MainWindowView"
				Icon="/Assets/avalonia-logo.ico"
				Title="Tests">

	<Design.DataContext>
		<vm:MainWindowViewModel/>
	</Design.DataContext>

	<Grid RowDefinitions="* *" ColumnDefinitions="* *" ShowGridLines="True">
		<TextBlock Grid.Row="0" Grid.Column="0" Width="100" Height="100" Background="Red"
							 IsPointerOver="{Binding IsActive, Mode=OneWayToSource}" Text="{Binding IsActive, Mode=OneWay}" />
		
		<TextBlock Grid.Row="1" Grid.Column="1" Width="100" Height="100" Background="Blue"
							 IsPointerOver="{Binding IsActive, Mode=OneWayToSource}" Text="{Binding IsActive, Mode=OneWay}" />
	</Grid>
</Window>

ViewModel:

using ReactiveUI;

namespace Tests.ViewModels
{
	public class MainWindowViewModel : ReactiveObject
	{
		bool _isActive;
		public bool IsActive
		{
			get => _isActive;
			set => this.RaiseAndSetIfChanged( ref _isActive, value );
		}
	}
}

Result:
After executing and moving mouse over red or blue square I get infinity loop in set => this.RaiseAndSetIfChanged( ref _isActive, value );.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions