Answer OK so adding the suggested code given by E-Bat didn't have any affect until I started a new project and copied all the code across verbatim. I can only assume there must be some background code within the ViewModelLocator on http://prismlibrary.com/ which did not update to take the parameterless constructor into account. Hope this helps anyone else with the same issue
Original Question I have set up a MVVM project using prism. I have a MainWindow.xaml and 5 Views; ButtonsView, HeaderView, ProcessInputView, ProcessLogView and ProcessSelectionView which I am using, each View has an associated ViewModel.
MainWindow.xaml
<Window x:Class="TransactionAutomationTool.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TransactionAutomationTool"
xmlns:views="clr-namespace:TransactionAutomationTool.Views"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d"
Title="MainWindow" Height="600" Width="800">
<Grid>
<views:HeaderView x:Name="HeaderViewControl" Margin="20,21,0,0" />
<views:ProcessSelectionView x:Name="ProcessSelectionViewControl" Margin="20,119,0,0" />
<views:ProcessInputView x:Name="ProcessInputViewControl" Margin="20,280,0,0" />
<views:ProcessLogView x:Name="ProcessLogView" Margin="298,105,0,0" />
<views:ButtonsView x:Name="ButtonViewControl" Margin="0,513,0,0" />
</Grid>
MainWindowViewModel
public class MainWindowViewModel: BindableBase
{
public IEventAggregator _events;
private UserPrincipal userPrincipal;
public MainWindowViewModel(IEventAggregator events)
{
_events = events;
userPrincipal = UserPrincipal.Current;
_events.GetEvent<HeaderLoaded>().Subscribe(HeaderHasBeenLoaded);
}
private void HeaderHasBeenLoaded()
{
_events.GetEvent<UserNameUpdate>().Publish(string.Format("{0} {1}", userPrincipal.GivenName, userPrincipal.Surname));
}
}
When I try to view the MainWindow in design mode I get the following Error Screenshot of MainWindow In design Mode
No Parameterless constructor found for this object - This Highlights the HeaderView and the ButtonsView
Both the HeaderViewModel and ButtonsViewModel take IEventAggregator as a parameter within their constructor where as the rest of the ViewModels do not. I am assuming this is where the errors are coming from.
HeaderViewModel
public class HeaderViewModel: BindableBase
{
private string userName;
private string runTime;
public string UserName
{
get { return userName; }
set { SetProperty(ref userName, value); }
}
public string RunTime
{
get { return runTime; }
set { SetProperty(ref runTime, value); }
}
public HeaderViewModel(IEventAggregator events)
{
events.GetEvent<RunTimeUpdate>().Subscribe(RunTimeUpdated);
events.GetEvent<UserNameUpdate>().Subscribe(UserNameUpdated);
events.GetEvent<HeaderLoaded>().Publish();
}
private void RunTimeUpdated(string newRunTime)
{
RunTime = newRunTime;
}
private void UserNameUpdated(string userName)
{
UserName = userName;
}
}
So how can I get round this error if I need to subscribe to these events and hence need the IEventAggregator passed into my ViewModels?
Do I need to register this within the Bootstrap via an override of the ConfigureContainer method? If so I'm not entirely sure how to do this.
Bootstrap
class Bootstraper: UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void InitializeShell()
{
Application.Current.MainWindow.Show();
}
}
The application builds successfully and runs successfully but it is just when trying to view the MainWindow in the designer that I get this message.
Any help would be greatly appreciated. EDIT All my view constructors just have the initalizeComponent methods and take no parameters
Your view is trying to execute logic that only make sense at runtime, so you need to make sure that you are not in design mode:
public HeaderView()
{
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
{
var svc = ServiceLocator.Current;
var eventAggregator = svc.GetInstance<IEventAggregator>();
this.DataContext = new HeaderViewModel(eventAggregator);
}
InitializeComponent();
}
EDIT:
For support of designtime view model have a look here
Basically you need to provide a parameterless constructor for you ViewModel to support design mode.