[英]Pluggable .NET 4.5 Ribbon
I am looking for a way to provide a pluggable way to add items to the .NET 4.5 ribbon, and have made a few strides in doing so, but not quite the way I'd like it:我正在寻找一种方法来提供一种可插入的方式来向 .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));
}
}
While this works, it seems messy.虽然这有效,但看起来很混乱。 I'd prefer to write all of the plugins' content in XAML.
我更喜欢用 XAML 编写所有插件的内容。 Is there a way I can achieve this goal?
有没有办法实现这个目标?
Everything I've looked at references the old Ribbon or some other library.我看过的所有内容都引用了旧的 Ribbon 或其他一些库。
Thanks.谢谢。
I had the same issues so far.到目前为止,我遇到了同样的问题。 The goals I've planned to achieve:
我计划实现的目标:
RibbonTabViewModel
, RibbonButtonViewModel
, etc), because this leads to parallel hierarchy of classes, and limits the abilities of XAML.RibbonTabViewModel
、 RibbonButtonViewModel
等),因为这会导致类的并行层次结构,并限制 XAML 的能力。 Here's the approach I've used.这是我使用的方法。
All my plugins are decorated with [ApplicationExtension(...)]
and implement IApplicationExtension
:我所有的插件都装饰有
[ApplicationExtension(...)]
并实现IApplicationExtension
:
public interface IApplicationExtension
{
void Startup();
bool CanShutdown();
void Shutdown();
}
ApplicationExtension
is declared as: 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
- some metadata, such as display name, etc. IApplicationExtensionMetadata
- 一些元数据,例如显示名称等。
Host application, in turn, implements this interface:反过来,主机应用程序实现了这个接口:
public interface IApplicationInfrastructureProvider : IInfrastructureProvider
{
ICollection<ViewModel> RibbonTabs { get; }
ICollection<ViewModel> ApplicationMenuItems { get; }
ICollection<ViewModel> QuickAccessToolbarItems { get; }
ICollection<ViewModel> StatusBarItems { get; }
}
where ViewModel
- some base view model class, and loads plugins via MEF:其中
ViewModel
- 一些基本视图模型类,并通过 MEF 加载插件:
[ImportMany]
private IEnumerable<Lazy<IApplicationExtension, IApplicationExtensionMetadata>> Extensions { get; set; }
When application initializes, it calls Startup
method for each plugin.当应用程序初始化时,它为每个插件调用
Startup
方法。
Here plugin implementation is able to add tabs, menu items, etc. via IApplicationInfrastructureProvider
as view models to extend application's UI.这里插件实现能够通过
IApplicationInfrastructureProvider
添加选项卡、菜单项等作为视图模型来扩展应用程序的 UI。
Note, that these view models are not any RibbontTabViewModel
or RibbonButtonViewModel
.请注意,这些视图模型不是任何
RibbontTabViewModel
或RibbonButtonViewModel
。 They are just some pieces of functionality.它们只是一些功能。
How it works at the UI side.它是如何在 UI 端工作的。
When, for example, RibbonTabs
collection is changed, application calls custom service, which performs this job:例如,当
RibbonTabs
集合发生更改时,应用程序会调用自定义服务,该服务执行此工作:
MyCustomVm
, the service looks for MyCustom.xaml
in the same assembly.MyCustomVm
,则该服务会在同一程序集中查找MyCustom.xaml
。_RibbonTabKey
._RibbonTabKey
结尾的资源。 View model becomes the data context of found resource.FrameworkElement
.FrameworkElement
。RibbonTabsUI
collection of host application.RibbonTabsUI
集合中。 The ribbon is bound to the RibbonTabsUI
in XAML for host application:功能区绑定到主机应用程序的 XAML 中的
RibbonTabsUI
:
<r:Ribbon x:Name="ribbon" Grid.Row="0" ItemsSource="{Binding RibbonTabsUI}">
<!-- other content -->
</r:Ribbon>
The sample of ribbon tab looks like this:功能区选项卡的示例如下所示:
<r:RibbonTab x:Key="MyCustom_RibbonTabKey" x:Shared="False">
<r:RibbonGroup Header="Some group">
<!-- other content -->
</r:RibbonGroup>
<!-- other content -->
</r:RibbonTab>
ApplicationMenuItems
and QuickAccessToolbarItems
are being processed the same way, the difference is the resource key suffix. ApplicationMenuItems
和QuickAccessToolbarItems
的处理方式相同,区别在于资源键后缀。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.