Wpf MEF和插件属性更新

Wpf MEF和插件属性更新,wpf,vb.net,mef,Wpf,Vb.net,Mef,我是MEF的新手,开始了一个项目来测试它。我想做的是打开一个MainForm,加载基于接口的插件。这些插件需要能够在它们之间交换信息,MainForm也应该能够与所有插件通信。因此,我开始创建加载插件的MainForm。插件只是一个包含列表框的表单。主窗体上有一个按钮。我希望该按钮向插件发送一个列表(字符串),该插件将该列表(字符串)加载到列表框中。目前,当我点击MainForm按钮时,它会将列表发送到插件。但是列表没有加载到插件列表框中。为了找出问题所在,我在MainForm上添加了一个新按钮

我是MEF的新手,开始了一个项目来测试它。我想做的是打开一个MainForm,加载基于接口的插件。这些插件需要能够在它们之间交换信息,MainForm也应该能够与所有插件通信。因此,我开始创建加载插件的MainForm。插件只是一个包含列表框的表单。主窗体上有一个按钮。我希望该按钮向插件发送一个列表(字符串),该插件将该列表(字符串)加载到列表框中。目前,当我点击MainForm按钮时,它会将列表发送到插件。但是列表没有加载到插件列表框中。为了找出问题所在,我在MainForm上添加了一个新按钮,以验证plugin属性是否包含我发送的列表(字符串)。是的,列表包含了我所有的字符串。问题应该是列表框没有刷新

接口的一部分:

Public Interface IPlugIn

   Property PlugInName as string
   Property Files As List(Of String)

End Interface
MainForm按钮中的代码:

    Dim currentPlugIn As Contract.API.IPlugIn

    currentPlugIn = PlugIns.Find(Function(x) x.PlugInName = "Test")

    currentPlugIn.Files = IO.Directory.GetFiles("SomeFolder").ToList
插件中的代码:

<Export(GetType(Contract.API.IPlugIn))> _
Public Class UserControl1
   Implements System.ComponentModel.INotifyPropertyChanged, Contract.API.IPlugIn

Public Property Files As System.Collections.Generic.List(Of String) Implements
   Contract.API.IPlugIn.Files
    Get
        If IsNothing(_files) Then
            _files = New List(Of String)
        End If

        Return _files
    End Get
    Set(value As System.Collections.Generic.List(Of String))
        _files = value

        OnPropertyChanged("Files")
    End Set
End Property

Public Event PropertyChanged(sender As Object, e As 
   System.ComponentModel.PropertyChangedEventArgs) Implements
   System.ComponentModel.INotifyPropertyChanged.PropertyChanged

Public Sub OnPropertyChanged(propertyName As String)
    RaiseEvent PropertyChanged(Me, New 
    ComponentModel.PropertyChangedEventArgs(propertyName))
End Sub
_
公共类UserControl1
实现System.ComponentModel.INotifyPropertyChanged、Contract.API.IPlugIn
公共属性文件作为System.Collections.Generic.List(字符串)实现
Contract.API.IPlugIn.Files
得到
如果没有(_文件),则
_文件=新列表(字符串)
如果结束
返回\u文件
结束
Set(值为System.Collections.Generic.List(字符串))
_文件=值
OnPropertyChanged(“文件”)
端集
端属性
公共事件属性已更改(发件人作为对象,e作为
System.ComponentModel.PropertyChangedEventArgs)实现
System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Public Sub OnPropertyChanged(propertyName作为字符串)
RaiseEvent属性已更改(Me、New)
ComponentModel.PropertyChangedEventArgs(propertyName))
端接头
插件XAML中的代码:

<ListBox Name="lstFiles" ItemsSource="{Binding Path=Files}"/>

有什么问题吗?我在互联网上搜索了数百个例子,但没有一个能说明如何做我想做的事情。在这里发布我的问题之前,我添加了INotifyPropertyChanged,它没有解决问题。我用PRISM,Caliburn,Micro会更好吗?还是MEF会没事


谢谢你的帮助

Athari,谢谢你的评论

我确实修复了ObservaleCollection的属性,但没有修复该问题。看来我还错过了什么

这是完整的代码

接口

Namespace API

   Public Interface IPlugIn

      Property Files As System.Collections.ObjectModel.ObservableCollection(Of String)
      ReadOnly Property PlugInUI As System.Windows.Controls.UserControl

   End Interface

End Namespace
插件

Imports System.ComponentModel.Composition

<Export(GetType(Contract.API.IPlugIn))> _
Public Class UserControl1
Implements Contract.API.IPlugIn, System.ComponentModel.INotifyPropertyChanged, 
   System.Collections.Specialized.INotifyCollectionChanged

Private _files As System.Collections.ObjectModel.ObservableCollection(Of String)

Public Property Files As System.Collections.ObjectModel.ObservableCollection(Of String)     
  Implements Contract.API.IPlugIn.Files
    Get
        If IsNothing(_files) Then
            _files = New System.Collections.ObjectModel.ObservableCollection(Of String)
        End If
        Return _files
    End Get
    Set(value As System.Collections.ObjectModel.ObservableCollection(Of String))
        _files = value
        OnPropertyChanged("Files")
        OnCollectionChanged(New 
          Collections.Specialized.NotifyCollectionChangedEventArgs _
          (Specialized.NotifyCollectionChangedAction.Reset))
    End Set
End Property

Public ReadOnly Property PlugInUI As System.Windows.Controls.UserControl Implements 
Contract.API.IPlugIn.PlugInUI
    Get
        Dim myUI As New UserControl1

        Return myUI
    End Get
End Property

Public Event PropertyChanged(sender As Object, e As 
    System.ComponentModel.PropertyChangedEventArgs) Implements      
    System.ComponentModel.INotifyPropertyChanged.PropertyChanged

Public Sub OnPropertyChanged(Optional propertyName As String = Nothing)
    RaiseEvent PropertyChanged(Me, New 
      ComponentModel.PropertyChangedEventArgs(propertyName))
End Sub

Public Event CollectionChanged(sender As Object, e As 
  System.Collections.Specialized.NotifyCollectionChangedEventArgs) Implements 
  System.Collections.Specialized.INotifyCollectionChanged.CollectionChanged

Public Sub OnCollectionChanged(args As 
  System.Collections.Specialized.NotifyCollectionChangedEventArgs)
    RaiseEvent CollectionChanged(Me, args)
End Sub

End Class
导入System.ComponentModel.Composition
_
公共类UserControl1
实现Contract.API.IPlugIn、System.ComponentModel.INotifyPropertyChanged、,
System.Collections.Specialized.InotifyCollections已更改
私有的_文件,如System.Collections.ObjectModel.ObservableCollection(字符串)
作为System.Collections.ObjectModel.ObservableCollection(字符串)的公共属性文件
实现Contract.API.IPlugIn.xml文件
得到
如果没有(_文件),则
_files=New System.Collections.ObjectModel.ObservableCollection(字符串)
如果结束
返回\u文件
结束
集合(值为System.Collections.ObjectModel.ObservableCollection(字符串))
_文件=值
OnPropertyChanged(“文件”)
OnCollectionChanged(新的
Collections.Specialized.NotifyCollectionChangedEventArgs_
(专用.NotifyCollectionChangedAction.Reset))
端集
端属性
公共只读属性PlugInUI作为System.Windows.Controls.UserControl实现
Contract.API.IPlugIn.PlugInUI
得到
将myUI设置为新用户控件1
返回myUI
结束
端属性
公共事件属性已更改(发件人作为对象,e作为
System.ComponentModel.PropertyChangedEventArgs)实现
System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Public Sub OnPropertyChanged(可选propertyName As String=Nothing)
RaiseEvent属性已更改(Me、New)
ComponentModel.PropertyChangedEventArgs(propertyName))
端接头
公共事件集合已更改(发件人作为对象,e作为
System.Collections.Specialized.NotifyCollectionChangedEventArgs)实现
System.Collections.Specialized.INotifyCollectionChanged.CollectionChanged
公共子集合已更改(参数为
System.Collections.Specialized.NotifyCollectionChangedEventArgs)
RaiseEvent集合已更改(Me、args)
端接头
末级
插件XAML

<Grid>
    <ListBox Height="248" HorizontalAlignment="Left" Margin="30,31,0,0" Name="ListBox1" 
     VerticalAlignment="Top" Width="241" ItemsSource="{Binding Files}">
</Grid>

主机应用程序

Imports System.ComponentModel.Composition
Imports System.ComponentModel.Composition.Hosting

Public Class HostApp

<ImportMany(GetType(Contract.API.IPlugIn))> _
Public Property PlugIns As List(Of Contract.API.IPlugIn)
Private _container As CompositionContainer

Public Sub Compose()
    Dim catalog As New AggregateCatalog

    catalog.Catalogs.Add(New DirectoryCatalog("pluginfolder"))

    _container = New CompositionContainer(catalog)

    _container.ComposeParts(Me)
End Sub

Public Sub LoadPlugIns()
    Compose()

    For Each item In PlugIns
        Desktop.Children.Add(item.PlugInUI)
    Next
End Sub

Private Sub HostApp_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) 
Handles Me.Loaded
    LoadPlugIns()
End Sub

Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) 
Handles Button1.Click
    Dim fileList As New Collections.ObjectModel.ObservableCollection(Of String)

    For Each fileItem As String In IO.Directory.GetFiles("Somefolder")
        fileList.Add(fileItem)
    Next

    PlugIns.Item(0).Files = fileList
End Sub

End Class
导入System.ComponentModel.Composition
导入System.ComponentModel.Composition.Hosting
公共类主机应用程序
_
公共属性插件列表(Contract.API.IPlugIn)
专用容器作为CompositionContainer
公共子组件()
Dim目录作为新的AggregateCatalog
catalog.Catalogs.Add(新目录目录(“pluginfolder”))
_容器=新合成容器(目录)
_容器组件(Me)
端接头
公共子加载插件()
撰写()
对于插件中的每个项目
Desktop.Children.Add(item.PlugInUI)
下一个
端接头
已加载私有子主机app_(发件人作为对象,e作为System.Windows.RoutedEventArgs)
对付我,上膛了
LoadPlugIns()
端接头
私有子按钮1\u单击(发件人作为System.Object,e作为System.Windows.RoutedEventArgs)
手柄按钮1。单击
Dim文件列表作为新集合.ObjectModel.ObservableCollection(字符串的集合)
对于IO.Directory.GetFiles(“Somefolder”)中的字符串形式的每个文件项
fileList.Add(fileItem)
下一个
PlugIns.Item(0).Files=fileList
端接头
末级
我需要在插件列表框中列出文件属性


再次感谢你的帮助

Athari,谢谢你的评论

我确实修复了ObservaleCollection的属性,但没有修复该问题。看来我还错过了什么

这是完整的代码

接口

Namespace API

   Public Interface IPlugIn

      Property Files As System.Collections.ObjectModel.ObservableCollection(Of String)
      ReadOnly Property PlugInUI As System.Windows.Controls.UserControl

   End Interface

End Namespace
插件

Imports System.ComponentModel.Composition

<Export(GetType(Contract.API.IPlugIn))> _
Public Class UserControl1
Implements Contract.API.IPlugIn, System.ComponentModel.INotifyPropertyChanged, 
   System.Collections.Specialized.INotifyCollectionChanged

Private _files As System.Collections.ObjectModel.ObservableCollection(Of String)

Public Property Files As System.Collections.ObjectModel.ObservableCollection(Of String)     
  Implements Contract.API.IPlugIn.Files
    Get
        If IsNothing(_files) Then
            _files = New System.Collections.ObjectModel.ObservableCollection(Of String)
        End If
        Return _files
    End Get
    Set(value As System.Collections.ObjectModel.ObservableCollection(Of String))
        _files = value
        OnPropertyChanged("Files")
        OnCollectionChanged(New 
          Collections.Specialized.NotifyCollectionChangedEventArgs _
          (Specialized.NotifyCollectionChangedAction.Reset))
    End Set
End Property

Public ReadOnly Property PlugInUI As System.Windows.Controls.UserControl Implements 
Contract.API.IPlugIn.PlugInUI
    Get
        Dim myUI As New UserControl1

        Return myUI
    End Get
End Property

Public Event PropertyChanged(sender As Object, e As 
    System.ComponentModel.PropertyChangedEventArgs) Implements      
    System.ComponentModel.INotifyPropertyChanged.PropertyChanged

Public Sub OnPropertyChanged(Optional propertyName As String = Nothing)
    RaiseEvent PropertyChanged(Me, New 
      ComponentModel.PropertyChangedEventArgs(propertyName))
End Sub

Public Event CollectionChanged(sender As Object, e As 
  System.Collections.Specialized.NotifyCollectionChangedEventArgs) Implements 
  System.Collections.Specialized.INotifyCollectionChanged.CollectionChanged

Public Sub OnCollectionChanged(args As 
  System.Collections.Specialized.NotifyCollectionChangedEventArgs)
    RaiseEvent CollectionChanged(Me, args)
End Sub

End Class
导入System.ComponentModel.Composition
_
公共类UserControl1
实现Contract.API.IPlugIn、System.ComponentModel.INotifyPrope
Public Sub OnImportsSatisfied() Implements 
System.ComponentModel.Composition.IPartImportsSatisfiedNotification.OnImportsSatisfied
    For Each plugInItem In WidgetList
        Desktop.Children.Add(plugInItem)
    Next
End Sub