将嵌套视图连接到 Prism 4.0 和 MEF 中的视图模型

发布于 2024-10-06 03:27:46 字数 3554 浏览 0 评论 0原文

我是 MEF 的新手,试图弄清楚如何构建我的 Prism 4.0 应用程序以将视图连接到视图模型。我的用例是,我有一个用户控件嵌套在另一个用户控件中。我想将嵌套用户控件连接到其视图模型。我尝试遵循 Prism 4.0 示例,但不确定我是否使用 MEF 最佳实践。

以下是我的应用程序中的一些片段来演示该问题。 HomeView 有一个名为 HelloView 的嵌套用户控件。我需要将 HelloView 连接到其名为 HelloViewModel 的视图模型。当前状态下的代码不起作用。我认为 HelloView 不是由 MEF 构建的,因此 HelloViewModel 没有被连接。

***** HomeModule *****
[ModuleExport(typeof(HomeModule))]
public class HomeModule : IModule
{
    IRegionManager _regionManager;

    [ImportingConstructor]
    public HomeModule(IRegionManager regionManager)
    {
        _regionManager = regionManager;
    }

    public void Initialize()
    {
        // Create the view
        IHomeView homeView = ServiceLocator.Current.GetInstance<IHomeView>();

        // Add it to the region
        IRegion region = _regionManager.Regions["MainRegion"];
        region.Add(homeView, "HomeView");
        region.Activate(homeView);
    }
}


****** IHomeView *****
public interface IHomeView
{
}


***** HomeView.xaml *****
<UserControl ...>

    <Grid x:Name="LayoutRoot">
        <view:HelloView x:Name="helloView"/>
    </Grid>

</UserControl>


***** HomeView.xaml.cs *****
[Export(typeof(IHomeView))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class HomeView : UserControl, IHomeView
{
    public HomeView()
    {
        InitializeComponent();
    }
}


***** IHelloView *****
public interface IHelloView
{
}


***** HelloView.xaml *****
<UserControl ...>
    <StackPanel x:Name="LayoutRoot" Margin="10">
        <StackPanel Orientation="Horizontal" VerticalAlignment="Top">
            <TextBlock Text="Name" VerticalAlignment="Center" />
            <TextBox Width="100" VerticalAlignment="Center" Margin="10 0 0 0"
                     Text="{Binding Path=Name, Mode=TwoWay}" />
            <Button Content="Submit" VerticalAlignment="Center" Margin="10 0 0 0"
                    Command="{Binding SubmitCommand}"/>
        </StackPanel>
        <TextBlock Text="{Binding Message}" Margin="0 10 0 0" Foreground="Red" />
    </StackPanel>
</UserControl>

***** HelloView.xaml.cs *****
[Export(typeof(IHelloView))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class HelloView : UserControl, IHelloView
{
    public HelloView()
    {
        InitializeComponent();
    }

    [Import]
    public IHelloViewModel ViewModel
    {
        set { this.DataContext = value; }
    }
}


***** IHelloViewModel *****
public interface IHelloViewModel
{
}


***** HelloViewModel *****
[Export(typeof(IHelloViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HelloViewModel : NotificationObject, IHelloViewModel
{
    public HelloViewModel()
    {
        this.SubmitCommand = new DelegateCommand<object>(this.OnSubmit);
    }

    private void OnSubmit(object obj)
    {
        Message = "Hello " + Name;
    }

    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            if (value != _name)
            {
                _name = value;
                this.RaisePropertyChanged("Name");
            }
        }
    }

    private string _message;
    public string Message
    {
        get { return _message; }
        set
        {
            if (value != _message)
            {
                _message = value;
                this.RaisePropertyChanged("Message");
            }
        }
    }

    public ICommand SubmitCommand { get; private set; }
}

I am a newbie on MEF and trying to figure out how to structure my Prism 4.0 application to connect views to view models. My use case is that I have one user control nested inside another user control. I would like to connect the nested user control to its view model. I have tried to follow Prism 4.0 examples but not sure if I am using MEF best practices.

Here are some snippets from my application to demonstrate the issue. HomeView has a nested user control called HelloView. I need to connect HelloView to its view model called HelloViewModel. The code in its current state does not work. I think HelloView is not being constructed by MEF and hence HelloViewModel is not being connected.

***** HomeModule *****
[ModuleExport(typeof(HomeModule))]
public class HomeModule : IModule
{
    IRegionManager _regionManager;

    [ImportingConstructor]
    public HomeModule(IRegionManager regionManager)
    {
        _regionManager = regionManager;
    }

    public void Initialize()
    {
        // Create the view
        IHomeView homeView = ServiceLocator.Current.GetInstance<IHomeView>();

        // Add it to the region
        IRegion region = _regionManager.Regions["MainRegion"];
        region.Add(homeView, "HomeView");
        region.Activate(homeView);
    }
}


****** IHomeView *****
public interface IHomeView
{
}


***** HomeView.xaml *****
<UserControl ...>

    <Grid x:Name="LayoutRoot">
        <view:HelloView x:Name="helloView"/>
    </Grid>

</UserControl>


***** HomeView.xaml.cs *****
[Export(typeof(IHomeView))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class HomeView : UserControl, IHomeView
{
    public HomeView()
    {
        InitializeComponent();
    }
}


***** IHelloView *****
public interface IHelloView
{
}


***** HelloView.xaml *****
<UserControl ...>
    <StackPanel x:Name="LayoutRoot" Margin="10">
        <StackPanel Orientation="Horizontal" VerticalAlignment="Top">
            <TextBlock Text="Name" VerticalAlignment="Center" />
            <TextBox Width="100" VerticalAlignment="Center" Margin="10 0 0 0"
                     Text="{Binding Path=Name, Mode=TwoWay}" />
            <Button Content="Submit" VerticalAlignment="Center" Margin="10 0 0 0"
                    Command="{Binding SubmitCommand}"/>
        </StackPanel>
        <TextBlock Text="{Binding Message}" Margin="0 10 0 0" Foreground="Red" />
    </StackPanel>
</UserControl>

***** HelloView.xaml.cs *****
[Export(typeof(IHelloView))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class HelloView : UserControl, IHelloView
{
    public HelloView()
    {
        InitializeComponent();
    }

    [Import]
    public IHelloViewModel ViewModel
    {
        set { this.DataContext = value; }
    }
}


***** IHelloViewModel *****
public interface IHelloViewModel
{
}


***** HelloViewModel *****
[Export(typeof(IHelloViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HelloViewModel : NotificationObject, IHelloViewModel
{
    public HelloViewModel()
    {
        this.SubmitCommand = new DelegateCommand<object>(this.OnSubmit);
    }

    private void OnSubmit(object obj)
    {
        Message = "Hello " + Name;
    }

    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            if (value != _name)
            {
                _name = value;
                this.RaisePropertyChanged("Name");
            }
        }
    }

    private string _message;
    public string Message
    {
        get { return _message; }
        set
        {
            if (value != _message)
            {
                _message = value;
                this.RaisePropertyChanged("Message");
            }
        }
    }

    public ICommand SubmitCommand { get; private set; }
}

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

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

发布评论

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

评论(1

甜尕妞 2024-10-13 03:27:46

你的解决方案没问题,我只有两个注释:
第一:如果您的目录包含超过 1 种类型的 IHelloViewModel(这很可能是因为您相应地有多个视图和视图模型),那么您会收到组合错误,因为导入返回多个结果。

[Import]public IHelloViewModel ViewModel

应该是这样的

[Import(typeof(HelloViewModel))] IHelloViewModel ViewModel

,或者你只是让你的财产像:

   [Import]
public HelloViewModel ViewModel

第二:
不要使用 ServiceLocator 来创建 HomeViewServiceLocator 旨在创建单例实例,而 EventAggregator 是完美的候选者。视图不应共享(并且您正确地将其标记为 [PartCreationPolicy(CreationPolicy.NonShared)] - 否则,如果您想将视图添加到另一个区域,则会出现错误。)

使用

   [Import]
    public HomeView HomeView 

希望这有帮助。

Your solution is OK, I only have 2 notes:
First: If your catalog contains more than 1 type of IHelloViewModel (that is most likely because you have several views and viewmodels correspondingly) then you get a composition error because import returns more than one result.

[Import]public IHelloViewModel ViewModel

should be something like

[Import(typeof(HelloViewModel))] IHelloViewModel ViewModel

or you just make your property like:

   [Import]
public HelloViewModel ViewModel

Second:
Do dont use ServiceLocator for the creation of your HomeView. ServiceLocator is intended to create the singleton instances and EventAggregator is the perfect candidate for that. Views should be not shared (and you correctly marked it as [PartCreationPolicy(CreationPolicy.NonShared)] - otherwise is you want to add your view to another region you get error.)
)

use

   [Import]
    public HomeView HomeView 

Hope this helps.

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