1

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

部分界面:

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

插件 XAML 中的代码:

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

有什么问题?我在互联网上搜索示例并找到数百个示例,但没有一个显示如何做我想做的事。就在这里发布我的问题之前,我添加了 INotifyPropertyChanged,它没有解决问题。对我来说,使用 PRISM、Caliburn.Micro 或者 MEF 会更好吗?

谢谢你的帮助!

4

2 回答 2

1

感谢大家!

我终于找到了答案。

我实现了 PRISM EventAggregator 并更改了以下内容

在界面和插件中

完全移除

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 Sub OnImportsSatisfied() Implements 
System.ComponentModel.Composition.IPartImportsSatisfiedNotification.OnImportsSatisfied
    For Each plugInItem In WidgetList
        Desktop.Children.Add(plugInItem.PlugInView)
    Next
End Sub

Public Sub OnImportsSatisfied() Implements 
System.ComponentModel.Composition.IPartImportsSatisfiedNotification.OnImportsSatisfied
    For Each plugInItem In WidgetList
        Desktop.Children.Add(plugInItem)
    Next
End Sub

现在一切都如我所愿!

于 2013-09-19T12:57:18.463 回答
0

阿塔里,谢谢你的评论。

我确实将属性修复为 ObservableCollection,但没有解决问题。似乎我还缺少其他东西。

这是完整的代码。

界面

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

插件 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

我需要将 Files 属性列在 PlugIn ListBox 中。

再次感谢你的帮助!

于 2013-09-09T17:24:23.383 回答