I am using Caliburn.Micro to try to bind items in a ListBox to one of two views but a single viewmodel. I am able to display the items in the ListBox, but when any item is selected I get 'Cannot find view for CustomerViewModel.'
Here are the relevant pieces of this application:
AppBootstrapper:
public class AppBootstrapper : BootstrapperBase
{
public AppBootstrapper()
: base()
{
Initialize();
}
protected override void OnStartup(object sender, StartupEventArgs e)
{
base.DisplayRootViewFor<CustomerWorkspaceViewModel>();
}
}
In my Views/Customers folder I have a CustomerViewModel:
public class CustomerViewModel : Screen
{
private string name;
public string Name
{
get { return name; }
set
{
name = value;
NotifyOfPropertyChange(() => Name);
}
}
}
and a CustomerWorkspaceViewModel:
public class CustomerWorkspaceViewModel : DocumentWorkspace<CustomerViewModel>
{
private CustomerViewModel selectedItem;
public CustomerViewModel SelectedItem
{
get { return selectedItem; }
set
{
selectedItem = value;
NotifyOfPropertyChange(() => SelectedItem);
}
}
public CustomerWorkspaceViewModel()
{
Items.AddRange(
new ObservableCollection<CustomerViewModel>
{
new CustomerViewModel {Name = "Customer 1" },
new CustomerViewModel {Name = "Customer 2" },
new CustomerViewModel {Name = "Customer 3" }
});
}
}
I have four views in my Views/Customers folder: In a Views/Customers/CustomerWorkspace, I have and Edit View and an Read view:
Edit.xaml:
<Grid>
<StackPanel>
<Label Content="Edit View"/>
<TextBlock Foreground="White"
FontSize="20"
Text="{Binding Name}" />
</StackPanel>
</Grid>
and Read.xaml:
<Grid>
<TextBlock Foreground="White"
FontSize="20"
Text="{Binding Name}" />
<Label Content="Read view"/>
</Grid>
Finally I have an empty CustomerView user control in Views/Customers, and a CustomerWorkspaceView in Views/Customers:
<Grid>
<ListBox x:Name="Items"
Margin="5"
SelectedItem="{Binding SelectedItem}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" Margin="5" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ContentControl cal:View.Context="{Binding State, Mode=TwoWay}" cal:View.Model="{Binding SelectedItem}"/>
</Grid>
Finally I have DocumentWorkspace, at the root folder, with AppBootstrapper:
public abstract class DocumentWorkspace<TDocument> : Conductor<TDocument>.Collection.OneActive
where TDocument : class, INotifyPropertyChanged, IDeactivate, IHaveDisplayName
{
public enum DocumentWorkspaceState
{
Read,
Edit
}
DocumentWorkspaceState state = DocumentWorkspaceState.Read;
public DocumentWorkspaceState State
{
get { return state; }
set
{
if (state == value)
return;
state = value;
NotifyOfPropertyChange(() => State);
}
}
}
What I am desiring (and expecting) is when selecting an item in the ListBox, which is composed of DocumentWorkspace objects, which are Conductors, to switch from one view (Edit) to another (Read). The select is working, the SelectedItem setter is getting fired, and the State in DocumentWorkspace is set correctly. But Caliburn.Micro cannot seem to find the view for the resulting CustomerViewModel that is SelectedItem. I've really tried to include in this post only what is needed to reproduce the problem here.
Note the documentation for what I am trying to do follows the discussion at