1

我正在使用 Prism 和 Managed Extensibility Framework 编写带有 WPF 的应用程序。目的是允许开发人员在那里创建自己的第 3 方模块。为了尽可能多地删除工作,我在一个 Common 模块中创建了一些基类,这些基类已经完成了大部分所需的工作。(例如,拖放视图,添加 MEF InheritedExportAttribute)。这些控件之一称为ModuleControl(派生自UserControl),如下所示。

如果我的模块有一个直接派生自XAML 中的UserControl一个孩子的视图类,那么我的一切工作都很好ModuleControl(参见下面的示例)。这对用户来说似乎是很多额外的工作。我想让我的视图类仅使用代码从“ModuleControl”派生。如果我按照下面的最后一个示例执行此操作,则 RegisterViewWithRegion 将引发以下异常:

Activation error occured while trying to get instance of type ModuleView, key \"\"  
System.Exception    {Microsoft.Practices.ServiceLocation.ActivationException}

我意识到当类型无法注册时会发生这种情况。所以我的问题是我怎样才能做到这一点?我究竟做错了什么?RegisterViewWithRegion 是否明确期望 UserControl 并没有从中派生任何东西?

这是我位于 Common.dll 中的第一个控件的示例。

namespace Common.Controls
{
    [InheritedExport]
    public partial class ModuleControl: UserControl
    {
       private Point _anchor;

       public ModuleControl()
       {
           InitializeComponent();
       }

       public ObservableCollection<IComponent> ModuleComponents
       {
         get
         {
              return (ObservableCollection<IComponent>)GetValue(ModuleComponentsProperty);
         }
         set
         {
              SetValue(ModuleComponentsProperty, value);
         }
    }

    private void  InitialiseCollection()
    {
        try
        {
            ModuleComponents = new ObservableCollection<IComponent>();              
            var components = ServiceLocator.Current.GetAllInstances(typeof(IComponent));
            Assembly controlAssembly = UIHelper.FindAncestor<UserControl>(VisualTreeHelper.GetParent(this)).GetType().Assembly;

            foreach (IComponent c in components)
            {
                if (c.ExportType.Assembly.Equals(controlAssembly))
                {
                    ModuleComponents.Add(new Component(c.ViewType, c.Description));
                }
            }
        }
        catch (Exception e)
        {

        }
    }


    public string ModuleName
    {
        get 
        {
            return (string)GetValue(ModuleNameProperty);
        }
        set
        {
            SetValue(ModuleNameProperty, value);
        }
    }

    public static readonly DependencyProperty ModuleComponentsProperty =
        DependencyProperty.Register("ModuleComponents", typeof(ObservableCollection<IComponent>), typeof(ModuleControl), new UIPropertyMetadata(null));

    public static readonly DependencyProperty ModuleNameProperty =
        DependencyProperty.Register("ModuleName", typeof(String), typeof(ModuleControl), new UIPropertyMetadata("No Module Name Defined"));



    private void DragList_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        // Store the mouse position
        _anchor = e.GetPosition(null);
    }

    private void DragList_PreviewMouseMove(object sender, MouseEventArgs e)
    {
        // Get the current mouse position
        Point mousePos = e.GetPosition(null);
        Vector diff = _anchor - mousePos;

        if (e.LeftButton == MouseButtonState.Pressed &&
            Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
            Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance)
        {
            // Get the dragged ListViewItem
            ListView listView = sender as ListView;
            ListViewItem listViewItem = UIHelper.FindAncestor<ListViewItem>((DependencyObject)e.OriginalSource);

            // Initialize the drag & drop operation
            if (listViewItem != null)
            {
                DataObject dragData = new DataObject("moduleFormat", listViewItem.Content);
                DragDrop.DoDragDrop(listViewItem, dragData, DragDropEffects.Move);
            }
        } 
    }

    private void moduleControl_LayoutUpdated(object sender, EventArgs e)
    {
        if (ModuleComponents == null)
            InitialiseCollection();
    }
}

根据示例A Prism 4 Application Checklist,我构建了以下模块,将其修改为在适当的情况下使用 MEF 而不是 Unity:

该模块位于 RandomNumbers.dll

namespace RandomNumbers
{
    [ModuleExport(typeof(RandomNumberModule))]
    public class RandomNumberModule: IModule
    {
        public void Initialize()
        {
            var regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();
            regionManager.RegisterViewWithRegion("MyRegion", typeof(ModuleView));
        }
    }
}

有效的ModuleViewXAML 如下所示:

<UserControl x:Name="userControl" x:Class="RandomNumbers.Views.ModuleView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:common="clr-namespace:Common.Base;assembly=Common"
         xmlns:commonctrls="clr-namespace:Common.Controls;assembly=Common"
         mc:Ignorable="d">
     <commonctrls:ModuleControl x:Name="moduleControl" ModuleName="Random Number Module"  />
</UserControl>

其背后的代码是:

namespace RandomNumbers.Views
{
    [Export]
    public partial class ModuleView : UserControl
    {
        private Point startPoint;
        public ModuleView()
        {
             InitializeComponent();

        }
    }
}

如前所述,上述所有代码都可以完美运行。但是,如果我用它替换 XAML 和后面的代码,那么我会得到所描述的异常。我试过省略ExportAttribute但没有任何改变。

namespace RandomNumbers.Views
{
    [Export(typeof(UserControl))]
    public class ModuleView : ModuleControl
    {
        public ModuleView() : base() { }
    }
}
4

0 回答 0