- File > New Project > New WPF Application.
- Add nuget package Caliburn.Micro.
- Delete MainWindow.xaml.
- Create the Views and ViewModels folders.
- Add new class MainShellViewModel(inherit from "Screen") to the ViewModels folder.
- Add new window MainShellView to the Views folder.
- Add new class Bootstrapper to the root folder.
//Bootstrapper.cs
class Bootstrapper : BootstrapperBase
{
private SimpleContainer container;
public Bootstrapper()
{
Initialize();
}
protected override void Configure()
{
container = new SimpleContainer();
container.Instance(container);
container
.Singleton<IWindowManager, WindowManager>()
.Singleton<IEventAggregator, EventAggregator>();
container
.PerRequest<MainShellViewModel>();
/*.PerRequest<OtherShellViewModel>(); //Other viewmodels*/
}
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor<MainShellViewModel>();
}
protected override object GetInstance(Type service, string key)
{
return container.GetInstance(service, key);
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return container.GetAllInstances(service);
}
protected override void BuildUp(object instance)
{
container.BuildUp(instance);
}
protected override void OnUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = false;
MessageBox.Show(e.Exception.Message, "An error has occurred", MessageBoxButton.OK);
}
}
- Remove StartupUri from the Application element in App.xaml.
- Add Bootstrapper as a resource
<!-- App.xaml -->
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<local:Bootstrapper x:Key="Bootstrapper" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Add Fody injections for PropertyChanged
- Install PropertyChanged.Fody from nuget
<!-- FodyWeavers.xml -->
<Weavers>
<PropertyChanged EventInvokerNames="NotifyOfPropertyChange" />
</Weavers>
- Add "[AddINotifyPropertyChangedInterface]" attribute to VM classes
container.GetInstance<IWindowManager>().ShowWindow(container.GetInstance<OtherViewModel>());
<TextBox Text="{Binding CodeSearchText, UpdateSourceTrigger=PropertyChanged }"
cal:Message.Attach="[Event GotFocus] = [Action CodeSearchTextBoxGotFocus($dataContext)]; [Event TextChanged] = [Action CodeSearchTextChangedAsync($eventArgs)]" />
<TabControl x:Name="Items" TabStripPlacement="Left">
<TabControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button cal:Message.Attach="CloseTab($dataContext)" Content="X" Padding="5,0,5,0" Margin="5" />
<TextBox Text="{Binding CodeSearchText, UpdateSourceTrigger=PropertyChanged }" Width="150"
cal:Message.Attach="[Event GotFocus] = [Action CodeSearchTextBoxGotFocus($dataContext)]; [Event TextChanged] = [Action CodeSearchTextChangedAsync($eventArgs)]" />
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
public class TabControlViewModel : Conductor<ItemViewModel>.Collection.OneActive
{
private SimpleContainer container;
public CodeSearchTabsViewModel(SimpleContainer container)
{
this.container = container;
ActivateItem(container.GetInstance<CodeSearchTabContentViewModel>());
}
public void CodeSearchTextBoxGotFocus(CodeSearchTabContentViewModel dc)
{
ActivateItem(dc);
if(Items.IndexOf(dc) == (Items.Count - 1))
{
Items.Add(container.GetInstance<CodeSearchTabContentViewModel>());
}
}
public void CloseTab(CodeSearchTabContentViewModel dc)
{
DeactivateItem(dc, true);
}
}