Как заставить работать связку MEF+WPF MVVM

223
10 марта 2019, 14:30

В своем приложении функцию хочу вынести как расширение, для этого прочитал и попробовал MEF, но нет примеров нормальных по использованию этой технологии в связке с MVVM WPF. Сам вопрос, как сделать так, чтобы юзерконтрол кнопка с командой импортировалась в приложение. Наглядный пример упростил до вот этого. Приложение состоит из трех сборок. Сборка Contract в виде dll, состоит из двух интерфейсов

namespace Contract
{
    public interface Iextension
    {
        string Name { get; }
        FrameworkElement GetUI();
    }
}
namespace Contract
{
    public interface Icontrol
    {
         void Metod_For_control(MessageBoxResult messageBoxResult);
    }
}

Сборка с самим расширением в ввиде юзерконтрола для WPF

using System.ComponentModel.Composition;
using System.Windows;
using System.Windows.Controls;
using Contract;
namespace Metod_and_button
{
    /// <summary>
    /// Логика взаимодействия для buttonUserControl1.xaml
    /// </summary>
    [Export(typeof(Iextension))]
    public partial class buttonUserControl1 : UserControl, Iextension
    {
        [Import(typeof(Icontrol))]
        Icontrol t;

        public buttonUserControl1()
        {
            InitializeComponent();
        }
        public void Clic(object sender,RoutedEventArgs e)
        {
            t.Metod_For_control(MessageBox.Show("jfjfjfj")); 
        }

        public FrameworkElement GetUI()
        {
            return this;
        }
       public new string Name
        {
            get { return "bvz"; }
        }
    }
}

xaml

<UserControl x:Class="Metod_and_button.buttonUserControl1"
             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:local="clr-namespace:Metod_and_button"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Grid HorizontalAlignment="Left" Height="177" Margin="100,146,0,0" VerticalAlignment="Top" Width="580">
            <Button Content="Button" HorizontalAlignment="Left" Height="52" Margin="157,69,0,0" VerticalAlignment="Top" Width="236"/>
        </Grid>
    </Grid>
</UserControl>

И само хост приложение в виде wpf MVVM ViewModel

using Contract;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.IO;
namespace WpfApp2.viewmodel
{
    [Export(typeof(Icontrol))]
    class MainViewModel : INotifyPropertyChanged
    {
// импортирую расширения
        [ImportMany(typeof(Iextension))]
        private IEnumerable<Iextension> _libraryDataServices { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
        public IEnumerable<Iextension> LibraryDataServices
        {
            get { return _libraryDataServices; }
        }
        private Iextension _selectedLibrary;
        public Iextension SelectedLibrary
        {
            get { return _selectedLibrary; }
            set
            {
                _selectedLibrary = value;
                if (value == null)
                   Books.Clear();
                _selectedLibrary.GetUI();
                OnPropertyChanged("SelectedLibrary");
            }
        }
        private ObservableCollection<Icontrol> _books;
        public ObservableCollection<Icontrol> Books
        {
            get { return _books; }
            set
            {
                _books = value;
                OnPropertyChanged("Books");
            }
        }
        // конструктор
        public MainViewModel()
        {
            // импортируем расширения
            DoImport();
        }
        private void DoImport()
        {
            //An aggregate catalog that combines multiple catalogs
            var catalog = new AggregateCatalog();
            //Add all the parts found in all assemblies in
            //the same directory as the executing program
            var path = Path.Combine(Directory.GetCurrentDirectory(), "Plugins");
            catalog.Catalogs.Add(new DirectoryCatalog(path));
            //Create the CompositionContainer with the parts in the catalog.
            var container = new CompositionContainer(catalog);
            //Fill the imports of this object
            container.ComposeParts(this);
        }
    }
}

View

 public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Loaded += MainWindow_Loaded;
        }
        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            DataContext = new MainViewModel();
        }
    }

xaml с местом для вывода кнопки

<Window x:Class="WpfApp2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp2"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid HorizontalAlignment="Left" Height="242" Margin="45,80,0,0" VerticalAlignment="Top" Width="717">
            <ListView ItemsSource="{Binding LibraryDataServices}" HorizontalAlignment="Left" Height="124" Margin="99,59,0,0" VerticalAlignment="Top" Width="446">
                <ListView.View>
                    <GridView>
                        <GridViewColumn/>
                    </GridView>
                </ListView.View>
            </ListView>
        </Grid>
    </Grid>
</Window>
READ ALSO
C# WPF ListBoxItem задать ControlTemplate для каждого ListBoxItem

C# WPF ListBoxItem задать ControlTemplate для каждого ListBoxItem

Как задать ControlTemplate для каждого ListBoxItem внутри ListBox? Например я могу в XAML добавить ListBoxItem внутри ListBox и задать ему Template но если мне нужно забиндить...

134
Уникальные поля EF Core 2.1

Уникальные поля EF Core 2.1

Есть база данных с двумя таблицами: Users и FollowersДля доступам к данным используется EF Core 2

168
Visual Studio 2017 не работает режим отладки

Visual Studio 2017 не работает режим отладки

Проблема в следующемПри запуске проекта через

226