Connecting a subview to view a model in Prism 4.0 and MEF

I am new to MEF and trying to figure out how to structure the Prism 4.0 application for connecting views to view models. My use case is that I have one user control nested in another user control. I would like to associate a nested user control with its view model. I tried to follow the examples of Prism 4.0, but not sure if I am using the best practices of MEF.

Here are some snippets from my application to demonstrate this problem. HomeView has a nested HelloView user control. I need to associate HelloView with its HelloViewModel view model. The code in its current state does not work. I think that HelloView is not created by MEF and therefore, HelloViewModel is not 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; }
}
+3
source share
1 answer

Your solution is fine, I have only 2 notes: First: if your catalog contains more than 1 type of IHelloViewModel (this is most likely because you have several views and visible models, respectively), you get a composition error, because that import returns more than one result.

[Import]public IHelloViewModel ViewModel

should be something like

[Import(typeof(HelloViewModel))] IHelloViewModel ViewModel

or you just create your property:

   [Import]
public HelloViewModel ViewModel

-:   ServiceLocator HomeView. ServiceLocator singleton EventAggregator . ( [PartCreationPolicy(CreationPolicy.NonShared)] - , .) )

   [Import]
    public HomeView HomeView 

, .

+1

Source: https://habr.com/ru/post/1778768/


All Articles