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.
精彩评论