1

Prism と Managed Extensibility Framework を使用して、WPF でアプリケーションを作成しています。目的は、開発者が独自のサードパーティ モジュールを作成できるようにすることです。できるだけ多くの作業を削除するために、必要な作業のほとんどを既に行っている共通モジュールにいくつかの基本クラスを作成しました。(例: ビューのドラッグ アンド ドロップ、 MEF の追加InheritedExportAttribute)。これらのコントロールの 1 つは、以下に示すように呼び出されますModuleControl(から派生しUserControlます)。

UserControlXAMLで 1 つの子から直接派生したビュー クラスがモジュールにある場合、すべてがうまく機能します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();
    }
}

Prism 4 アプリケーション チェックリストの例に従って、必要に応じて Unity の代わりに MEF を使用するようにこれを変更して、次のモジュールを作成しました。

このモジュールは 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