Search code examples
c#xamlavaloniaui

Really simple menu example?


Using VS2022 on Windows 10 21H2 with Avalonia Toolkit and Avalonia for VS2022 installed.

TL;DR:

  1. A MenuItem with Command="{Binding MainWindow.OnOpenCommand}"is greyed out.
  2. MenuItem myMenu = this.FindControl<MenuItem>("FileOpen"); returns myMenu as expected but the Command property is null.

What am I doing wrong?

I've created an absolutely vanilla 'Hello World' project with the following XAML as per the documentation here: https://docs.avaloniaui.net/docs/controls/menu.

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        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="AvaloniaApplication1.MainWindow"
        Title="AvaloniaApplication1">
        <DockPanel VerticalAlignment="Top">
          <Menu DockPanel.Dock="Top">
            <MenuItem Header="_File">
              <MenuItem Name="FileOpen" IsEnabled="True" Header="_Open..." Command="{Binding OpenCommand}" CommandParameter="{Binding ElementName=MainWindow}"/><Separator/>
              <MenuItem Header="_Exit"/>
            </MenuItem>
            <MenuItem Header="_Edit" >
              <MenuItem Header="Copy"/>
              <MenuItem Header="Paste"/>
            </MenuItem>
          </Menu>
        </DockPanel>
</Window>

The associated C# code is:

using Avalonia.Controls;
using System.Windows.Input;
using System.Reactive;
using System;

namespace AvaloniaApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            // yep, this works. we find the control
            MenuItem myMenu = this.FindControl<MenuItem>("FileOpen");
            // how to wire this up in code ????
            // myMenu.Command = openCommand;
        }
        //
        public bool CanExitCommand()
        {
            return true;
        }
        public void OnExitCommand() 
        {
            int i = 0;
        }
        //
        public bool CanOpenCommand()
        {
            return true;
        }
        public void OnOpenCommand()
        {
            int i = 0;
        }
    }
}

Solution

  • The solution is to be found in the binding directive. One simple method, as there are apparently alternatives, is this: Command="{Binding $parent[Window].OnOpenCommand}"

    [Edit] Previous example removed as almost certainly deprecated by Avalonia advances.