Reputation: 872
I have a listbox to select an item for edit. I have an edit button as well. Call this the MainView[Model].
If I press the edit button the MainView[Model] shall be replaced by EditView[Model]. The EditView shall not be displayed in a area below or beside the MainView. It should be completely replaced or at least completely hide the MainView.
If edit is finished (OK, cancel) the MainView shall be displayed again.
I have tried to overlay a ContentControl but with no success. Now, I'm thinking about a kind of NavigatorViewModel which has multiple ViewModels exposed by a property. But I'm not sure if this is the right direction to go.
Can anybody help?
Thx.
Upvotes: 0
Views: 667
Reputation: 4481
You would preferably use the Conductor pattern that Caliburn.Micro provides. A conductor manages one or more Screens and controls their lifetime. See Screens, Conductors and Composition for further information.
At first, we need a shell. This is your "NavigatorViewModel". It is derived from Conductor<Screen>.Collection.OneActive
, what means that it holds a list of Screens of which a single one can be active at a time:
public interface IShell
{
void ActivateItem(Screen screen);
}
public class ShellViewModel : Conductor<Screen>.Collection.OneActive, IShell
{
public ShellViewModel()
{
this.ActivateItem(new MainViewModel());
}
}
A conductor has an ActiveItem
property, and we want to bind a ContentControl
to it, so we see the corresponding view:
<!-- ShellView.xaml -->
<Window x:Class="WpfApplication1.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ContentControl Name="ActiveItem" />
</Window>
Our MainViewModel
can navigate to the EditViewModel
using its parent, the shell:
public class MainViewModel : Screen
{
public void Edit()
{
((IShell)this.Parent).ActivateItem(new EditViewModel());
}
}
We bind a button to the Edit
method:
<!-- MainView.xaml -->
<UserControl x:Class="WpfApplication1.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Button Name="Edit" Content="Edit" />
</UserControl>
EditViewModel
also derives from Screen and just contains your edit logic:
public class EditViewModel : Screen
{
}
Finally, we bind a button to the TryClose
method, so the view model closes itself and is removed from the shell's items. The last activated item (MainViewModel
) will be reactivated:
<!-- EditView.xaml -->
<UserControl x:Class="WpfApplication1.EditView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Button Name="TryClose" Content="Back" />
</UserControl>
That's about it.
Upvotes: 2