将 Blazor 与 Electron.NET 结合使用,当我单击 MenuItem 时,如何在组件内执行代码?

Posted

技术标签:

【中文标题】将 Blazor 与 Electron.NET 结合使用,当我单击 MenuItem 时,如何在组件内执行代码?【英文标题】:Using Blazor with Electron.NET, how can I execute code inside a component whenever I click on a MenuItem? 【发布时间】:2021-08-04 15:39:27 【问题描述】:

我正在使用 Blazor 服务器。 在我的启动中,我正在像这样配置 MenuItems:

var menu = new[]

    new MenuItem
    
        Label = "File", Submenu = new[]
        
            new MenuItem
            
                Label = "Save", 
                Accelerator = "CmdOrCtrl+S", 
                Enabled = false,
                Click = () =>
                
                    // How do I execute code inside my component?
                ,
            
        
    
;

Electron.Menu.SetApplicationMenu(menu);

我的组件位于根目录并且总是被渲染。它有一个名为Save 的简单方法,我想调用它。

public async Task SaveProject()

    await Project.Save();

在静态 Electron 类中是否有某种我可以使用的事件?类似OnMenuItemClicked

在我的组件中拥有一个我可以访问的静态属性不仅是糟糕的设计,它还会阻止我访问任何实例属性。

【问题讨论】:

【参考方案1】:

我自己想出了一个或多或少适用的解决方案。 我创建了一个单例服务 IMenuItemService,我在 Startup 和 Component 中都使用它。由于 MenuItems 本身没有 ID,因此我创建了一个单独的 Enum MenuItemType 来分隔它们。该服务如下所示:

public class MenuItemService : IMenuItemService

    public Action<MenuItemType> MenuItemClicked  get; set; 

    private Dictionary<MenuItemType, MenuItem> ConfigurableMenuItems  get; 

    public MenuItemService()
    
        ConfigurableMenuItems = new Dictionary<MenuItemType, MenuItem>();
        
        InitializeMenuItem(MenuItemType.Close, "Close Project", null, false);
    

    private void InitializeMenuItem(MenuItemType type, string label, string accelerator, bool enabled)
    
        ConfigurableMenuItems.Add(type, new MenuItem
        
            Label = label,
            Accelerator = accelerator,
            Enabled = enabled,
            Click = () =>  MenuItemClicked?.Invoke(type); ,
        );
    

    public void SetEnabled(MenuItemType menuItemType)
    
        ConfigurableMenuItems[menuItemType].Enabled = true;
        RenderMenuItems();
    
    
    public void SetDisabled(MenuItemType menuItemType)
    
        ConfigurableMenuItems[menuItemType].Enabled = false;
        RenderMenuItems();
    

    public void RenderMenuItems()
    
        Electron.Menu.SetApplicationMenu(new[]
        
            new MenuItem
            
                Label = "File", Submenu = new []
                
                    ConfigurableMenuItems[MenuItemType.Close]
                
            
        );
    

通过这种方法,我可以从应用程序中的任何位置(包括Startup.cs)调用menuItemService.RenderMenuItems(),而在我的组件中,我正在设置MenuItemClicked 操作以收听点击。

[Inject]
public IMenuItemService MenuItemService  get; set; 

private void InitializeMenuItemActions()

    MenuItemService.SetEnabled(MenuItemType.Close);
    
    MenuItemService.MenuItemClicked = type =>
    
        if (type == MenuItemType.Close)
        
            ProjectManager.CloseProject();
            NavigationManager.NavigateTo("/");
        
    ;

在我的例子中,我故意在 EventHandler 上使用 Action 属性,因为我的 MenuItem 不需要多个侦听器。

【讨论】:

以上是关于将 Blazor 与 Electron.NET 结合使用,当我单击 MenuItem 时,如何在组件内执行代码?的主要内容,如果未能解决你的问题,请参考以下文章

将 EfCore 延迟加载代理与 blazor 一起使用

将 datatables.net 与服务器端 Blazor 应用程序一起使用

Blazor 服务器:将 EF Core DbContextFactory 与 DbContext 混合

Blazor预研与实战

有啥方法可以与 blazor 页面的主要布局进行通信

将 B2C AD 用户存储与 Blazor 一起使用 - 陷入无限循环