Need some help with MEF,

Feb 24, 2012 at 10:07 AM

I am making an application in wpf following MVVM pattern. I need to add MEF into it.

Here is the basic architecture of my program.

I have a main project MefApplication. This has only one view MainWindow.xaml. This contains one listbox and a user control. When application runs it loads modules and list them down in the listbox. On clicking a module results in displaying module in the usercontrol.

Now for module, it is a WPF User Control Library. Now this module will contain different views. One a view there will be button which will be used to navigate to other views within a module.

Now I have loaded modules and listed them down. On clicking a module results in displaying first screen of a module. But when I click next button on the view of a module nothing happens. I dont know how to go to next view. Below is my code. Can anybody tells me where I am going wrong.

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainWindowViewModel();
    }
}

MainWindowViewModel.cs

class MainWindowViewModel : INotifyPropertyChanged
{
    #region NotifyOfPropertyChanged
    #endregion
 
    private string _path = "Path to Modules Dll Folder"; 
    public MainWindowViewModel()
    {
        Modules = GetModules(_path);
        SelectedModule = Modules[0];
    }
 
    public List<IMainModule> GetModules(string path)
    {
        var directoryCatalog = new DirectoryCatalog(path);
        var container = new CompositionContainer(directoryCatalog);
        var modules = container.GetExportedValues<IMainModule>().ToList();
        return modules;
    }
 
    private IMainModule selectedModule;
 
    public List<IMainModule> Modules { get; set; }
 
    public IMainModule SelectedModule
    {
        get { return selectedModule; }
        set
        {
            if (value != selectedModule)
            {
                selectedModule = value;
                NotifyOfPropertyChange("SelectedModule");
                NotifyOfPropertyChange("UserInterface");
            }
        }
    }
 
    public UserControl UserInterface
    {
        get
        {
            if (SelectedModule == null)
                return null;
            return SelectedModule.UserInterface;
        }
    }
}

This is the Module Interface. It contains module name and its starting view.

public interface IMainModule
{
    string Name { get; }
    UserControl UserInterface { get; }
}

This is one of my module. ServerWindowModule. This returns UserControl of one of my views in the module (ServerWindow).

[Export(typeof(IMainModule))]
class ServerWindowModule : IMainModule
{
    public string Name
    {
        get { return "Server Module"; }
    }
 
    public UserControl _userInterface { get; set; }
    public UserControl UserInterface
    {
        get { return _userInterface ?? (_userInterface = new ServerWindowView()); }
    }
}

This is one of my view. ServerWindowView.

public partial class ServerWindowView : UserControl
{
    public ServerWindowView()
    {
        InitializeComponent();
        DataContext = new ServerWindowViewModel();
    }
}

Now here is ViewModel for ServerWindowViewModel.

publicclassServerWindowViewModel : INotifyPropertyChanged { #region NotifyOfPropertyChanged #endregionpublic ServerWindowViewModel() { LabelText = "Constructor set this."; } publicstring LabelText { get; set; } privateICommand _nextCommand; publicICommand NextCommand { get { return _nextCommand ?? (_nextCommand = newRelayCommand(NextFunction)); } } publicvoid NextFunction() { LabelText = "Button set this."; NotifyOfPropertyChange("LabelText"); // TODO: Navigate to ServerValidation View

// Here i want to go to my next view (ServerValidationView). What should I write here. } }

Now on Next button function what should I do that replaces current view to ServerValidationView.

If there are any confusion then please ask.

Thanks,

Feb 24, 2012 at 4:29 PM

Hi – I suspect this is probably more a WPF question than a MEF one, you may need to seek out some WPF help (Stack Overflow is a great place to start.)

Just regarding the MEF aspects of the code, I would recommend creating only a single composition container at the top level of the application. A container needs to be kept alive as long as the parts in it are being used, so creating a temporary container in the GetModules() method isn’t a good approach.

Also, instead of using GetExportedValues() to retrieve the list of modules, you can just import them into the Modules property:

[ImportMany]

public List<IMainModule> Modules { get; set; }

To do this your MainWindowViewModel will itself have to be exported. MEF works best when you have parts connected up using Import/Export rather than by calling the container directly.

Hope this helps.

Nick

From: fhnaseer [email removed]
Sent: Friday, February 24, 2012 2:08 AM
To: Nicholas Blumhardt
Subject: Need some help with MEF, [MEF:344605]

From: fhnaseer

I am making an application in wpf following MVVM pattern. I need to add MEF into it.

Here is the basic architecture of my program.

I have a main project MefApplication. This has only one view MainWindow.xaml. This contains one listbox and a user control. When application runs it loads modules and list them down in the listbox. On clicking a module results in displaying module in the usercontrol.

Now for module, it is a WPF User Control Library. Now this module will contain different views. One a view there will be button which will be used to navigate to other views within a module.

Now I have loaded modules and listed them down. On clicking a module results in displaying first screen of a module. But when I click next button on the view of a module nothing happens. I dont know how to go to next view. Below is my code. Can anybody tells me where I am going wrong.

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainWindowViewModel();
    }
}

MainWindowViewModel.cs

class MainWindowViewModel : INotifyPropertyChanged
{
    #region NotifyOfPropertyChanged
    #endregion
 
    private string _path = "Path to Modules Dll Folder"; 
    public MainWindowViewModel()
    {
        Modules = GetModules(_path);
        SelectedModule = Modules[0];
    }
 
    public List<IMainModule> GetModules(string path)
    {
        var directoryCatalog = new DirectoryCatalog(path);
        var container = new CompositionContainer(directoryCatalog);
        var modules = container.GetExportedValues<IMainModule>().ToList();
        return modules;
    }
 
    private IMainModule selectedModule;
 
    public List<IMainModule> Modules { get; set; }
 
    public IMainModule SelectedModule
    {
        get { return selectedModule; }
        set
        {
            if (value != selectedModule)
            {
                selectedModule = value;
                NotifyOfPropertyChange("SelectedModule");
                NotifyOfPropertyChange("UserInterface");
            }
        }
    }
 
    public UserControl UserInterface
    {
        get
        {
            if (SelectedModule == null)
                return null;
            return SelectedModule.UserInterface;
        }
    }
}

This is the Module Interface. It contains module name and its starting view.

public interface IMainModule
{
    string Name { get; }
    UserControl UserInterface { get; }
}

This is one of my module. ServerWindowModule. This returns UserControl of one of my views in the module (ServerWindow).

[Export(typeof(IMainModule))]
class ServerWindowModule : IMainModule
{
    public string Name
    {
        get { return "Server Module"; }
    }
 
    public UserControl _userInterface { get; set; }
    public UserControl UserInterface
    {
        get { return _userInterface ?? (_userInterface = new ServerWindowView()); }
    }
}

This is one of my view. ServerWindowView.

public partial class ServerWindowView : UserControl
{
    public ServerWindowView()
    {
        InitializeComponent();
        DataContext = new ServerWindowViewModel();
    }
}

Now here is ViewModel for ServerWindowViewModel.

publicclassServerWindowViewModel : INotifyPropertyChanged

{

#region NotifyOfPropertyChanged

#endregionpublic ServerWindowViewModel()

{

LabelText = "Constructor set this.";

}

publicstring LabelText { get; set; }

privateICommand _nextCommand;

publicICommand NextCommand

{

get { return _nextCommand ?? (_nextCommand = newRelayCommand(NextFunction)); }

}

publicvoid NextFunction()

{

LabelText = "Button set this.";

NotifyOfPropertyChange("LabelText");

// TODO: Navigate to ServerValidation View

// Here i want to go to my next view (ServerValidationView). What should I write here.

}

}

Now on Next button function what should I do that replaces current view to ServerValidationView.

If there are any confusion then please ask.

Thanks,

Feb 27, 2012 at 5:38 AM

I am new to MEF. By doing too many import and export confuses me. I dont know which one to import/export and which one not to. Can you edit in the code. It will be really helpful.