在使用mef的wpf应用程序中需要帮助吗

在使用mef的wpf应用程序中需要帮助吗,wpf,mvvm,mef,Wpf,Mvvm,Mef,我正在wpf中按照MVVM模式制作一个应用程序。我需要加入MEF 这是我的程序的基本架构 我有一个主要项目mefaapplication。这只有一个视图MainWindow.xaml。它包含一个列表框和一个用户控件。当应用程序运行时,它加载模块并在列表框中列出它们。单击模块会导致在usercontrol中显示模块 现在对于模块来说,它是一个WPF用户控制库。现在,这个模块将包含不同的视图。一个视图将有一个按钮,用于导航到模块内的其他视图 现在我已经加载了模块并将它们列了下来。单击模块会显示模块的

我正在wpf中按照MVVM模式制作一个应用程序。我需要加入MEF

这是我的程序的基本架构

我有一个主要项目mefaapplication。这只有一个视图MainWindow.xaml。它包含一个列表框和一个用户控件。当应用程序运行时,它加载模块并在列表框中列出它们。单击模块会导致在usercontrol中显示模块

现在对于模块来说,它是一个WPF用户控制库。现在,这个模块将包含不同的视图。一个视图将有一个按钮,用于导航到模块内的其他视图

现在我已经加载了模块并将它们列了下来。单击模块会显示模块的第一个屏幕。但是,当我单击模块视图上的“下一步”按钮时,什么也没有发生。我不知道如何去下一个视图。下面是我的代码。谁能告诉我哪里出了问题

MainWindow.xaml

<Window x:Class="MefApplication.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="40*"/>
        <ColumnDefinition Width="80*"/>
    </Grid.ColumnDefinitions>
    <ListBox x:Name="listBox" Grid.Column="0" 
    ItemsSource="{Binding Modules}" SelectedItem="{Binding SelectedModule, Mode=TwoWay}" >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding ModuleName}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    <ContentPresenter x:Name="contentPresenter" Grid.Column="1" Content="{Binding UserInterface}"/>
</Grid>
</Window>
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;
        }
    }
} 
这是我的一个模块。服务器窗口模块。这将返回模块(ServerWindow)中我的一个视图的用户控制权

这是我的观点之一。ServerWindowView

public partial class ServerWindowView : UserControl
{
    public ServerWindowView()
    {
        InitializeComponent();
        DataContext = new ServerWindowViewModel();
    }
} 
下面是ServerWindowViewModel的ViewModel

publicclassServerWindowViewModel : INotifyPropertyChanged
{
    #region NotifyOfPropertyChanged
    #endregionpublic ServerWindowViewModel()
    {
        LabelText = "Constructor set this.";
    }

    publicstring LabelText { get; set; }

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

    public void 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.
    }
}          
现在在下一个按钮函数中,我应该做什么来将当前视图替换为ServerValidationView

如果有任何混淆,请询问


谢谢,

我目前正在做类似的事情。我不确定这是否是正确的处理方式,但我的设计是每个模块都有自己的外壳

例如,服务器窗口的第一个视图将是一个具有内容演示器的Shell。要更改模块内的视图,我将更改模块内演示者上的内容

这是一个基于我在

中看到的猜测,它可以帮助您实现这个或Rob Eisenberg在Mix上介绍的框架。它使用依赖属性

public static class View
{
    public static DependencyProperty ModelProperty =
        DependencyProperty.RegisterAttached(
            "Model",
            typeof(object),
            typeof(View),
            new PropertyMetadata(ModelChanged)
            );

    public static void SetModel(DependencyObject d, object value)
    {
        d.SetValue(ModelProperty, value);
    }

    public static object GetModel(DependencyObject d)
    {
        return d.GetValue(ModelProperty);
    }

    public static void ModelChanged(object sender, DependencyPropertyChangedEventArgs args)
    {
        if (args.NewValue == null || args.NewValue == args.OldValue)
            return;

        var vm = args.NewValue as IYourModuleProvidingUI;
        var view = vm.UserInterface;

        ((ContentControl)sender).Content = view;
    }
}
用法

<ContentControl Framework:View.Model="{Binding SelectedModule}" Padding="2,0,0,2"/>


SelectedViewModel
是一个属性,当其值发生更改时,会引发
INotifyPropertyChanged
事件。因此,将显示的内容由SelectedModule属性的值控制。

MainWindow发布相关xaml。xaml
@jberger您可以找到它。我已经编辑过了。
ContentPresenter
ContentControl
有时会让我窒息。您是否尝试了
ContentControl
?当
ListBox.SelectedItem
发生更改时,
MainWindowViewModel.UserInterface
属性是否会被命中?最后,我建议不要在
IMainModule
中使用
UserControl
。相反,对于实现
IMainModule
的每种类型,请在视图中定义一个
DataTemplate
。我有一个wpf用户控件库项目,其中包含多个视图(用户控件),我希望通过按钮事件浏览这些视图。
publicclassServerWindowViewModel : INotifyPropertyChanged
{
    #region NotifyOfPropertyChanged
    #endregionpublic ServerWindowViewModel()
    {
        LabelText = "Constructor set this.";
    }

    publicstring LabelText { get; set; }

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

    public void 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.
    }
}          
public static class View
{
    public static DependencyProperty ModelProperty =
        DependencyProperty.RegisterAttached(
            "Model",
            typeof(object),
            typeof(View),
            new PropertyMetadata(ModelChanged)
            );

    public static void SetModel(DependencyObject d, object value)
    {
        d.SetValue(ModelProperty, value);
    }

    public static object GetModel(DependencyObject d)
    {
        return d.GetValue(ModelProperty);
    }

    public static void ModelChanged(object sender, DependencyPropertyChangedEventArgs args)
    {
        if (args.NewValue == null || args.NewValue == args.OldValue)
            return;

        var vm = args.NewValue as IYourModuleProvidingUI;
        var view = vm.UserInterface;

        ((ContentControl)sender).Content = view;
    }
}
<ContentControl Framework:View.Model="{Binding SelectedModule}" Padding="2,0,0,2"/>