AvaloniaUI / Avalonia.Markup.Declarative

Provides helpers for declarative ui in C#
372 stars 21 forks source link

NativeMenu Sample #60

Closed IvanJosipovic closed 1 month ago

IvanJosipovic commented 2 months ago

Hi,

I am struggling to implement a NativeMenu in a declarative Window. Any suggestions?

Update, I managed to get it working with the following:

using AvaloniaEdit.Utils;

namespace App.Views;

public static class MainWindow
{
    public static Window Build(MainViewModel vm) =>
        (Window)new Window()
            .Title("App")
            .UseLayoutRounding(true)
            .SetProp(NativeMenu.MenuProperty, new NativeMenu()
                                                    .Items([
                                                        new NativeMenuItem()
                                                            .Header("File")
                                                            .Items([
                                                                new NativeMenuItem()
                                                                    .Header("Open")
                                                                    .Command(vm.OpenClustersCommand),

                                                                new NativeMenuItemSeparator(),

                                                                new NativeMenuItem()
                                                                    .Header("Close")
                                                                    .Command(vm.CloseCommand),
                                                                ])
            )
            .Content(
                new MainView()
            );
}

public static class WindowExtensions
{
    public static NativeMenu Items(this NativeMenu menu, NativeMenuItemBase[] items)
    {
        menu.Items.AddRange(items);

        return menu;
    }

    public static NativeMenuItem Items(this NativeMenuItem menu, NativeMenuItemBase[] items)
    {
        menu.Menu ??= [];

        menu.Menu.Items.AddRange(items);

        return menu;
    }
}
AArnott commented 2 months ago

I got it to work declaratively by adding this under the <Window> element:

  <NativeMenu.Menu>
    <NativeMenu>
      <NativeMenuItem Header="{Binding BackCommandCaption}" Command="{Binding NavigateBackCommand}" IsVisible="{Binding IsNavigateBackVisible}" />
      <NativeMenuItem Header="{Binding AppMenuCaption}">
        <NativeMenu>
          <NativeMenuItem Header="{Binding HomeCommandCaption}" Command="{Binding HomeCommand}" />
          <NativeMenuItem Header="{Binding AddressBookCommandCaption}" Command="{Binding AddressBookCommand}" />
          <NativeMenuItem Header="{Binding AccountsListCommandCaption}" Command="{Binding AccountsListCommand}" />
          <NativeMenuItemSeparator />
          <NativeMenuItem Header="{Binding SettingsCommandCaption}" Command="{Binding SettingsCommand}" />
          <NativeMenuItem Header="{Binding BackupCommandCaption}" Command="{Binding BackupCommand}" />
          <NativeMenuItemSeparator />
          <NativeMenuItem Header="{Binding AboutCommandCaption}" Command="{Binding AboutCommand}" />
        </NativeMenu>
      </NativeMenuItem>

      <NativeMenuItem Header="{Binding ToolsMenuCaption}">
        <NativeMenu>
          <NativeMenuItem Header="{Binding AddressCheckCommandCaption}" Command="{Binding AddressCheckCommand}" />
        </NativeMenu>
      </NativeMenuItem>
    </NativeMenu>
  </NativeMenu.Menu>
gritsenko commented 1 month ago

Here are variants of using native menu with TrayIcon (checked on Windows) and Window (not sure how it works, since I don't have access to osx at the moment)

var icon = AssetLoader.Open( new Uri($"avares://AvaloniaMarkupSample/avalonia-logo.ico"));

var menu = new NativeMenu().Items(
    new NativeMenuItem()
        .Header("File")
        .Items(
            new NativeMenuItem()
                .Header("Open")
                .OnClick(OnOpenClick),

            new NativeMenuItemSeparator(),

            new NativeMenuItem()
                .Header("Close")
                .OnClick(_ => Environment.Exit(0))
        )
);

appBuilder.Instance?.TrayIcon_Icons(
    [
        new TrayIcon()
            .Icon(new WindowIcon(icon))
            .Menu(menu)
    ]
);

lifetime.MainWindow = new Window()
    .Title("Avalonia markup samples")
    .Content(new MainView())
    .NativeMenu_Menu(menu);
gritsenko commented 1 month ago

added in https://www.nuget.org/packages/Avalonia.Markup.Declarative/11.2.0-beta4