我正在寻找一种方法来提供可插入的方式来将项目添加到 .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 模型不是任何RibbontTabViewModel
或RibbonButtonViewModel
。它们只是一些功能。
它在 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>
ApplicationMenuItems
和 QuickAccessToolbarItems
的处理方式相同,区别在于资源键后缀。
关于c# - 可插拔 .NET 4.5 功能区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23076248/