c# - 可插拔 .NET 4.5 功能区

标签 c# .net ribbon

我正在寻找一种方法来提供可插入的方式来将项目添加到 .NET 4.5 功能区,并且已经在这方面取得了一些进展,但并不完全是我想要的方式:

[InheritedExport]
public interface IRibbonItem
{
    void Compose(DesignerRibbon ribbon);
}

public class TestItem : IRibbonItem
{
    public void Compose(CustomRibbon ribbon)
    {
        ribbon.ApplicationMenu.Items.Add((new RibbonApplicationMenuItem() { Header = "_Hello, World!" }));
    }
}

public class MEFRibbon : System.Windows.Controls.Ribbon.Ribbon
{
    [ImportMany]
    private IEnumerable<IRibbonItem> _oRibbons = null;

    public MEFRibbon() : base()
    {
         this.ApplicationMenu = new RibbonApplicationMenu();
         MEFHelper.Instance.ComposeParts(this);
         this._oRibbons.ToList().ForEach(x => x.Compose(this));
    }
}

虽然这有效,但看起来很困惑。我更喜欢用 XAML 编写所有插件的内容。有什么办法可以实现这个目标吗?

我看过的所有内容都引用了旧的 Ribbon 或其他一些库。

谢谢。

最佳答案

到目前为止我也遇到了同样的问题。 我计划实现的目标:

  • 应用程序应可通过插件进行扩展。
  • 应用程序插件应该能够将自己的 UI 内容添加到预定义的 UI 区域:功能区选项卡、功能区应用程序菜单、功能区快速访问工具栏和状态栏。
  • 应用程序应尽可能在 MVVM 架构内构建。
  • 插件开发人员应该能够使用 XAML 描述 UI 内容。不应该有任何 View 模型类型,它会重现功能区控件的层次结构(例如 RibbonTabViewModel、RibbonButtonViewModel 等),因为这会导致类的并行层次结构,并且限制了 XAML 的能力。
  • 插件应使用 MEF 加载到主机应用程序中。

这是我使用的方法。
我的所有插件都用 [ApplicationExtension(...)] 装饰并实现 IApplicationExtension:

public interface IApplicationExtension
{
    void Startup();
    bool CanShutdown();
    void Shutdown();
}

ApplicationExtension 声明为:

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class ApplicationExtensionAttribute : ExportAttribute, IApplicationExtensionMetadata
{
    public ApplicationExtensionAttribute(/* ... */)
        : base(typeof(IApplicationExtension))
    {
        this.Name = name;
        this.UICompositionOrder = uiCompositionOrder;
    }

   // ...
}

IApplicationExtensionMetadata - 一些元数据,例如显示名称等

主机应用程序反过来实现此接口(interface):

public interface IApplicationInfrastructureProvider : IInfrastructureProvider
{
    ICollection<ViewModel> RibbonTabs { get; }
    ICollection<ViewModel> ApplicationMenuItems { get; }
    ICollection<ViewModel> QuickAccessToolbarItems { get; }
    ICollection<ViewModel> StatusBarItems { get; }
}

其中 ViewModel - 一些基本 View 模型类,并通过 MEF 加载插件:

    [ImportMany]
    private IEnumerable<Lazy<IApplicationExtension, IApplicationExtensionMetadata>> Extensions { get; set; }

当应用程序初始化时,它会为每个插件调用Startup方法。
这里的插件实现能够通过 IApplicationInfrastructureProvider 添加选项卡、菜单项等作为 View 模型来扩展应用程序的 UI。

请注意,这些 View 模型不是任何RibbontTabViewModelRibbonButtonViewModel。它们只是一些功能。

它在 UI 端的工作原理。
例如,当 RibbonTabs 集合发生更改时,应用程序会调用自定义服务来执行此作业:

  • 首先,它查找 View 模型的资源字典。为简单起见,我使用命名约定:如果选项卡 View 模型的类型为 MyCustomVm,则服务会在同一程序集中查找 MyCustom.xaml
  • 其次,该服务探索资源字典并查找 key 以 _RibbonTabKey 结尾的资源。 View 模型成为所找到资源的数据上下文。这假设该资源至少是 FrameworkElement
  • 第三,找到的资源将添加到主机应用程序的 RibbonTabsUI 集合中。

功能区绑定(bind)到主机应用程序的 XAML 中的 RibbonTabsUI:

<r:Ribbon x:Name="ribbon" Grid.Row="0" ItemsSource="{Binding RibbonTabsUI}">
    <!-- other content -->
</r:Ribbon>

功能区选项卡的示例如下所示:

<r:RibbonTab x:Key="MyCustom_RibbonTabKey" x:Shared="False">
    <r:RibbonGroup Header="Some group">
        <!-- other content -->
    </r:RibbonGroup>
    <!-- other content -->
</r:RibbonTab>

ApplicationMenuItemsQuickAccessToolbarItems 的处理方式相同,区别在于资源键后缀。

关于c# - 可插拔 .NET 4.5 功能区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23076248/

相关文章:

c# - 将多维(安全)数组从 C# 传递到 COM

C# 窗体 move 停止事件

c# - MVC EnumMember 自定义字符串

c# - 从另一个方法内部调用的方法的单元测试返回值

c# - Linq to nhibernate - 其中集合包含具有 id 的对象

.net - 参照父控件的类型设置DataTrigger的样式

.net - 任何人都可以向旧的 SNMP 小伙子解释 WMI 吗?

c# - 有没有办法免费使用 Office 2007 工具栏创建桌面应用程序?

c#-4.0 - System.ComponentModel.Design.ExceptionCollection

css - 如何使用 css 将丝带图像放在另一个图像上?