I'm using the Xceed toolkit WindowContainer and ChildWindows to generate a dynamic client area consisting of multiple windows (container), each containing multiple custom user controls (elements). These windows can be freely moved, resized and maximized in the WindowContainer area.
To represent the hierarchy at the ViewModel level I use Caliburn.Micros conductor mechanism. So the MainViewModel conducts containers:
public class MainViewModel : Conductor<ElementContainerViewModel>.Collection.AllActive
and the container conducts elements:
public class ElementContainerViewModel : Conductor<ElementViewModel>.Collection.AllActive
The corresponding views look like this (custom item control to replace the default ContentPresenter with a ChildWindow as container). MainView.xaml (ElementContainerView.xaml left out for brevity):
<childWindowContainer:MyItemsControl x:Name="Items" >
<childWindowContainer:MyItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<xctk:WindowContainer Height="800" Width="600" Background="LightGoldenrodYellow"/>
</ItemsPanelTemplate>
</childWindowContainer:MyItemsControl.ItemsPanel>
<childWindowContainer:MyItemsControl.ItemContainerStyle>
<Style>
<Setter Property="xctk:ChildWindow.Left" Value="{Binding ContainerLeft}" />
<Setter Property="xctk:ChildWindow.Top" Value="{Binding ContainerTop}" />
<Setter Property="xctk:ChildWindow.Width" Value="{Binding ContainerWidth}" />
<Setter Property="xctk:ChildWindow.Height" Value="{Binding ContainerHeight}" />
<Setter Property="xctk:ChildWindow.CloseButtonVisibility" Value="Collapsed" />
<Setter Property="xctk:ChildWindow.Content" Value="{Binding}" />
<Setter Property="xctk:ChildWindow.IsMaximized" Value="{Binding IsMaximized, Mode=TwoWay}" />
</Style>
</childWindowContainer:MyItemsControl.ItemContainerStyle>
</childWindowContainer:MyItemsControl>
The line that causes my headaches is the following, taken from the MainView itemscontrol:
<Setter Property="xctk:ChildWindow.Content" Value="{Binding}" />
The binding works fine, but the corresponding view isn't attached properly. So I just added an old-fashioned datatemplate to bind the container ViewModel to its corresponding view:
<DataTemplate DataType="{x:Type viewModels:ElementContainerViewModel}">
<views:ElementContainerView />
</DataTemplate>
The problem: since the ViewModel locator process isn't done by Caliburn.Micro anymore, closing the application leads to a nullreference exception for each ChildWindow which is caused by Caliburn.Micro closing the conducted ViewModels, but not closing the ElementContainerView.
How can I tell Caliburn.Micro to resolve that convention like I do in the datatemplate. The Views and ViewModels are of course properly organized so the default conventions can kick in (RootNS.ViewModels.ElementContainerViewModel.cs / RootNS.Views.ElementContainerView.xaml). I fiddled around using the ViewLocator.NameTransformer and the ConventionManager but couldn't get it to work.
ConventionManager.AddElementConvention<ChildWindow>(ContentControl.ContentProperty, "Content",
"DataContextChanged");
ViewLocator.NameTransformer.AddRule(@"^ElementContainerViewModel", @"ChildWindowContainer.Views.ElementContainerView");
Many thanks, Ly