Is there a way to reuse a WPF View using it with Caliburn.Micro?
In example I've got a DetailViewBase.xaml with a SaveAndClose and Cancel button. Now I want to use the DetailViewModelBase and the XAML in PersonView(Model).
I hope this is question is clear.
If my assumption is correct, I think what you mean is that you want to 'compose' a more complex view from several simpler viewmodels. You can inherit from viewmodels, but obviously a viewmodel can only have one active view at a time.
However, using bindings you can compose multiple viewmodels and have them all render their respective views together to make a more complex UI
e.g.
A VM with save/cancel buttons
public class ActionsViewModel
{
public void Save()
{
}
public void Cancel()
{
}
}
The corresponding view:
<UserControl>
<StackPanel Orientation="Horizontal">
<Button x:Name="Save">Save</Button>
<Button x:Name="Cancel">Cancel</Button>
</StackPanel>
</UserControl>
Another view which composes itself and the ActionsViewModel
public class ComposedViewModel
{
public ActionsViewModel ActionsView
{
get; set;
}
public ComposedViewModel()
{
ActionsView = new ActionsViewModel();
}
public void DoSomething()
{
}
}
The View:
<UserControl>
<StackPanel Orientation="Horizontal">
<TextBlock>Hello World</TextBlock>
<Button x:Name="DoSomething">Do Something</Button>
<ContentControl x:Name="ActionsView" />
</StackPanel>
</UserControl>
When you use the convention binding (or use the attached properties) to bind a ContentControl
CM will automatically bind the VM to the DataContext
and wire up the view. This way you can compose multiple VMs into a single more complex piece of functionality.
Additionally, because of the action message bubbling - if you were to remove the 'Ok' and 'Cancel' implementation on the ActionsViewModel
and put them in the ComposedViewModel
implementation, the action message will bubble up to the ComposedViewModel
instance and fire the methods on there instead
e.g.
public class ActionsViewModel
{
// Remove the command handlers
}
public class ComposedViewModel
{
public ActionsViewModel ActionsView
{
get; set;
}
public ComposedViewModel()
{
ActionsView = new ActionsViewModel();
}
public void DoSomething()
{
}
// CM will bubble the messages up so that these methods handle them when the user clicks on the buttons in the ActionsView
public void Save()
{
}
public void Cancel()
{
}
}
EDIT:
Sorry I forgot about this - convention based bindings won't allow messages to bubble, but you can just use the Message.Attach
attached property for this to work:
// Make sure you include the caliburn namespace:
<UserControl xmlns:cal="http://www.caliburnproject.org">
<StackPanel Orientation="Horizontal">
<Button x:Name="Save" cal:Message.Attach="Save">Save</Button>
<Button x:Name="Cancel" cal:Message.Attach="Cancel">Cancel</Button>
</StackPanel>
</UserControl>
You can bind the ViewModel to the View explicitly using code like this:
cal:Bind.Model={Binding DetailViewModelBase}