开发者

Connecting nested view to view model in Prism 4.0 and MEF

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开发者_JS百科 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; }
}


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜