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

发布于 2025-01-08 21:58:15 字数 4514 浏览 4 评论 0原文

我正在遵循 MVVM 模式在 wpf 中创建一个应用程序。我需要将 MEF 添加到其中。

这是我的程序的基本架构。

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

现在对于模块来说,它是一个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>

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;
        }
    }
} 

这是模块接口。它包含模块名称及其起始视图。

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

这是我的模块之一。服务器窗口模块。这将返回模块(ServerWindow)中我的视图之一的 UserControl。

[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()); }
    }
} 

这是我的看法之一。服务器窗口视图。

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。

如果有任何困惑,请询问。

谢谢,

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

<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>

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)); }
    }

    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.
    }
}          

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

If there are any confusion then please ask.

Thanks,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

酒儿 2025-01-15 21:58:15

Caliburn.Micro 可以帮助您解决此问题或 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 属性的值控制。

Caliburn.Micro can help you with this or the framework Rob Eisenberg presented on Mix. It uses dependency property

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;
    }
}

And usage

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

SelectedViewModel is a property raising INotifyPropertyChanged event when its value has changed. So what will be displayed is controlled by the value of the SelectedModule property.

独自←快乐 2025-01-15 21:58:15

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

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

这是基于我从 http://www.ra-design.at 看到的内容的疯狂猜测/silverlight/mediaowl/

I am currently doing something similar. I am not sure if this would be the correct way to handle it but my design is that each module would have its own Shell.

For example, the first view of your server window would be a Shell which has a content presenter. To change a view within a module I would change the content on the presenter within the module.

This is a wild guess based on what I saw from http://www.ra-design.at/silverlight/mediaowl/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文