Skip to content

Conversation

@ShapovalovKU
Copy link

@ShapovalovKU ShapovalovKU commented Dec 11, 2025

Describe the bug
Set IsChecked property from the UI breaks the binding to VM.

To Reproduce

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
        x:Class="Sandbox.MainWindow"
        xmlns:s="using:Sandbox"
        x:DataType="s:MainWindow">
  
<Grid RowDefinitions="Auto *">
  <Menu Name="MainMenu" Grid.Row="0"/>
  <StackPanel Orientation="Vertical" Grid.Row="1">
    <Button Content="Check" Command="{Binding Check}"/>
    <Button Content="Uncheck" Command="{Binding Uncheck}"/>
  </StackPanel>
</Grid>

</Window>
public partial class MainWindow : Window
{
    public event EventHandler<ItemSelectionChangedEventArgs>? SelectedChildChanged;

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;

        var node = new ChildWindowsNode();
        var menuNode = node.Build(this);

        MainMenu.Items.Add(menuNode.GetControl());
    }

    public void Check()
    {
        SelectedChildChanged?.Invoke(this, new ItemSelectionChangedEventArgs(new($"Item_1"), true));
    }

    public void Uncheck()
    {
        SelectedChildChanged?.Invoke(this, new ItemSelectionChangedEventArgs(new($"Item_1"), false));
    }
}

public class ItemSelectionChangedEventArgs(ItemVM item, bool isSelected) : EventArgs
{
    public ItemVM Item => item;

    public bool IsSelected => isSelected;
}

public record ItemVM(string Title);
<MenuItem xmlns="https://github.com/avaloniaui"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:m="using:Sandbox.TestMenu"
          x:DataType="m:ChildWindowsNode"
          ItemsSource="{Binding Items}"
          Header="Menu">

  <MenuItem.ItemContainerTheme>
    <ControlTheme TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}" x:DataType="{x:Type m:ViewHandleViewModel}">
      <Setter Property="Header" Value="{Binding Title}" />
      <Setter Property="IsChecked" Value="{Binding IsChecked, Mode=TwoWay}" />
      <Setter Property="ToggleType" Value="CheckBox"/>
    </ControlTheme>
  </MenuItem.ItemContainerTheme>
  
</MenuItem>
public abstract class NotificationObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

    protected void SetPropertyValue<T>(T value, ref T storage, [CallerMemberName] string propertyName = "")
    {
        if (Equals(value, storage))
            return;

        storage = value;
        OnPropertyChanged(propertyName);
    }

    protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

internal sealed class ViewHandleViewModel(string title, bool isChecked) : NotificationObject
{
    public string Title => title;

    public bool IsChecked
    {
        get => isChecked;
        set => SetPropertyValue(value, ref isChecked);
    }
}

internal class ChildWindowsNode
{
    private readonly ObservableCollection<ViewHandleViewModel> items = new();

    public IEnumerable<ViewHandleViewModel> Items => items;

    public MenuNode Build(MainWindow mainWindow)
    {
        mainWindow.SelectedChildChanged += (_, arg) =>
        {
            if (arg.Item?.Title is { } childTitle)
                UpdateSelection(childTitle, arg.IsSelected);
        };

        items.Add(new("Item_1", false));
        return new MenuNode(this);
    }

    private void UpdateSelection(string title, bool isSelected)
    {
        var item = items.FirstOrDefault(i => i.Title == title);
        if (item != null)
        {
            item.IsChecked = isSelected;
        }
    }

    public sealed class MenuNode(ChildWindowsNode owner)
    {
        public Control GetControl()
        {
            var menu = (MenuItem)AvaloniaXamlLoader.Load(new Uri("avares://Sandbox/TestMenu/ParentToggleMenuItem.axaml"));
            
            menu.DataContext = owner;
            return menu;
        }
    }
}

"Check" & "Uncheck" buttons works until item selected from menu.

Reproduce steps:

  1. Click in Menu->Item1
  2. Try uncheck with "Uncheck" button.

@ShapovalovKU ShapovalovKU force-pushed the fix/bug_menuitem_ischecked branch 3 times, most recently from 952c989 to 65ec0ac Compare December 11, 2025 10:35
@ShapovalovKU ShapovalovKU force-pushed the fix/bug_menuitem_ischecked branch from 65ec0ac to ceed7db Compare December 11, 2025 10:37
@maxkatz6
Copy link
Member

Do you have a repro to add specific unit tests?

@maxkatz6 maxkatz6 added bug backport-candidate-11.3.x Consider this PR for backporting to 11.3 branch labels Dec 12, 2025
@cla-avalonia
Copy link
Collaborator

cla-avalonia commented Dec 12, 2025

  • All contributors have signed the CLA.

@ShapovalovKU
Copy link
Author

@cla-avalonia agree

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-candidate-11.3.x Consider this PR for backporting to 11.3 branch bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants