C# 如何将数据从主机绑定到插件
如何使用MEF将数据从主机绑定到插件 所以问题是: 我使用MVVM,所以我有我的模型、视图模型和视图。 我想使用MEF来扩展我的应用程序。 我想在MainViewModel中存储所有数据,这样每个插件都可以处理实际数据。 该插件是一个用户控件,它将在MainViewModel中显示为ContentControl。 到目前为止,我所拥有的: 主视图模型 模型 从MainViewModel到视图的数据绑定。 从文件夹X导入插件 我需要的是: -插件需要将数据从MainViewModel绑定到插件UI。 -更改插件UI中的属性必须更新MainViewModel中的数据,并从所有其他插件更新UI 插件接口: MainViewModel:它的一部分C# 如何将数据从主机绑定到插件,c#,wpf,mvvm,data-binding,mef,C#,Wpf,Mvvm,Data Binding,Mef,如何使用MEF将数据从主机绑定到插件 所以问题是: 我使用MVVM,所以我有我的模型、视图模型和视图。 我想使用MEF来扩展我的应用程序。 我想在MainViewModel中存储所有数据,这样每个插件都可以处理实际数据。 该插件是一个用户控件,它将在MainViewModel中显示为ContentControl。 到目前为止,我所拥有的: 主视图模型 模型 从MainViewModel到视图的数据绑定。 从文件夹X导入插件 我需要的是: -插件需要将数据从MainViewModel绑定到插件UI
private MyModel myfirstmodel;
private DirectoryCatalog catalog;
private CompositionContainer container;
[ImportMany]
IEnumerable<Lazy<IPlugin, IPluginData>> Plugins;
public MainWindowViewModel()
{
string pluginPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
pluginPath = Path.Combine(pluginPath, "plugins");
if (!Directory.Exists(pluginPath))
Directory.CreateDirectory(pluginPath);
catalog = new DirectoryCatalog(pluginPath, "*.dll");
container = new CompositionContainer(catalog);
try
{
this.container.ComposeParts(this);
}
catch (CompositionException compositionException)
{
Console.WriteLine(compositionException.ToString());
}
}
插件
我尝试使用INotifyPropertyChanged,但没有成功
有没有人有一个非常好的教程,或者可以告诉我如何做到这一点?
我将非常感谢如何而不仅仅是使用InotifyProperty更改
这可能吗?对于使用ModelView交换数据,您需要一个表示主机的接口。您还需要一个容器或方法来插入表示插件的可视控件
interface IPluginHost
{
MyModelView ModelView {get;}
MyMainWindow View {get;}
}
interface IPlugin
{
void Register(IPluginHost host);
void Unregister();
}
合成后,您向主机注册插件,这将使它们能够访问模型视图:
this.container.ComposeParts(this);
foreach(var plugin in Plugins)
{
plugin.Value.Register(this);
}
我需要:-插件需要绑定来自
将MainViewModel添加到插件UI
如果插件可以执行所有必要的绑定,那么它可以通过它的Register方法访问MainViewModel。以下是许多方法之一:
public partial class MyFirstPlugin : UserControl, IPlugin
{
...
void Register(IPluginHost host)
{
_host = host;
// Attach main model view as data context
this.DataContext = host.ModelView;
// Add control to the host's container
var mainWindow = host.View;
mainWindow.AddPluginControl((UserControl)this);
}
void Unregister()
{
if (_host == null)
{
return;
}
this.DataContext = null;
_host.View.RemovePluginControl(this);
_host = null;
}
IPluginHost _host;
}
AddPluginControl、RemovePluginControl是将插件的可视元素插入容器中的公共方法。我个人认为你这样做是错误的,MEF是专门设计用于进行此类管道的,因此你不必这样做 在适当的MVVM应用程序中,视图通常通过数据模板创建,即使您不这样做,也通常需要导入其他全局数据,如画笔和行为等。如果您确实使用了您真正应该使用的模板,则不需要显式导出控件;通过模板简单地引用它们也会导致导入它们
您可以通过进口商的另一个通行证在实践中实现这一点。为每个插件提供一个定制的ResourceDictionary,并将所有全局数据/模板/UI资源等放在其中,因此它实际上是插件的App.xaml版本。诀窍是,然后给这些ResourceDictionary它们自己的代码隐藏文件,并用导出来修饰这些类。然后,主应用程序所要做的就是导入ResourceDictionary类型的所有类,或者最好是一个派生类或接口,该派生类或接口返回字典并将每个类添加到application.Current.Resources.MergedDictionaries。从这一点上讲,插件的开发与DLL项目中的插件开发几乎相同,而您正以通常的方式进行静态链接。。。我没有得到注册的那部分。。“Register”方法来自何处?它是什么?如果能找到解决这个问题的线索就好了cRegister是我添加到IPlugin接口声明中的一个方法。我在答案中添加了一个示例。好的。我现在通过插件注册得到了这个。但是我在哪里使用IPluginHost接口呢?我有一个模型视图,它在IPluginHost中使用,并组成所有插件。但是,当我将IPluginHost添加到ModelView时,我必须在MyModelView中设置IPluginHost.MyModelView。。这让我很困惑,你能给我举个简单的例子说明怎么做吗?以前从未使用过ResourceDirectories..:cI发现了6年前我自己最初学会的SO帖子,它是。你只需要记住初始化组件;在构造函数中,否则导入字典时字典将显示为空。谢谢。我试试看我想将UserControl添加到我的应用程序中。此UserControl将添加到总体视图中,并绑定视图中的数据。当主机中的数据更改时,usercontrol也必须更改。我该怎么做?@bene_rawr你可能不得不问第二个问题,关于你的具体情况,有更具体的细节,因为有很多不同的方式。一般来说,您可以将ContentControl与DataTemplate一起使用,也可以将样式与数据触发器一起使用。
interface IPluginHost
{
MyModelView ModelView {get;}
MyMainWindow View {get;}
}
interface IPlugin
{
void Register(IPluginHost host);
void Unregister();
}
this.container.ComposeParts(this);
foreach(var plugin in Plugins)
{
plugin.Value.Register(this);
}
public partial class MyFirstPlugin : UserControl, IPlugin
{
...
void Register(IPluginHost host)
{
_host = host;
// Attach main model view as data context
this.DataContext = host.ModelView;
// Add control to the host's container
var mainWindow = host.View;
mainWindow.AddPluginControl((UserControl)this);
}
void Unregister()
{
if (_host == null)
{
return;
}
this.DataContext = null;
_host.View.RemovePluginControl(this);
_host = null;
}
IPluginHost _host;
}