Reputation: 2415
I'm trying to implement copy&paste on WPF TreeView with Caliburn.Micro but I stuck at the beginning. Problem is that I don't know to get current item on TreeView was copied or pasted when event is invoked. Below is xaml for TreeView and event handler. Any suggestion?
<TreeView Name="Nodes" AllowDrop="True">
<TreeView.ContextMenu>
<ContextMenu ItemsSource="{Binding MenuItems}">
<MenuItem Header="Copy" cal:Message.Attach="[Event Click] = [Action Copy($source, $eventArgs)]"></MenuItem>
<MenuItem Header="Cut" cal:Message.Attach="[Event Click] = [Action Cut]"></MenuItem>
<MenuItem Header="Paste" cal:Message.Attach="[Event Click] = [Action Paste($this)]" IsEnabled="{Binding IsPasteEnabled}"></MenuItem>
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding Name}"/>
<Setter Property="IsEnabled" Value="{Binding IsEnabled}"/>
<Setter Property="Command" Value="{Binding MenuCommand}"/>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</TreeView.ContextMenu>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<HierarchicalDataTemplate ItemsSource="{Binding Childs}" DataType="{x:Type viewmodels:TreeListViewModel+Node}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
public void Copy(object sender, RoutedEventArgs args)
{
// to do...
}
Edited: Source: http://dfiles.eu/files/bsm545ti3
Upvotes: 1
Views: 1071
Reputation: 8656
This might not be useful, but I did something similar using the cal:Action.TargetWithoutContext
property to resolve the DataContext
to a particular ViewModel
. In my case I had several different types of ViewModel
all inheriting from a base TreeViewItemViewModel
class, but that shouldn't really be something you need to consider here.
Essentially, I was setting the DataContext
of the ContextMenu
to the actual ViewModel
represented by the current TreeView
node, allowing me to call an action I had defined on the ViewModel
.
In your case, you probably don't want a generic Copy/Paste defined on the ViewModel
, but you may be able to fire Copy
/Cut
/Paste
events (using the Caliburn.Micro
EventAggregator
), from each of the ViewModels
, passing themselves in the event information.
The important bit:
<ContextMenu cal:Action.TargetWithoutContext="{Binding DataContext, RelativeSource={RelativeSource Self}}">
I'd defined different a ContextMenu
depending on what the node represented, so it lived in the HierarchicalDataTemplate
. It looked something like this (I was using a StackPanel
to display multiple objects, allowing a ContextMenu
to appear if the StackPanel
itself was clicked.
<HierarchicalDataTemplate ItemsSource="{Binding Childs}"
DataType="{x:Type viewmodels:TreeListViewModel+Node}">
<StackPanel Orientation="Horizontal">
<StackPanel.ContextMenu>
<ContextMenu cal:Action.TargetWithoutContext="{Binding DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Cut" cal:Message.Attach="Cut" />
<MenuItem Header="Copy" cal:Message.Attach="Copy" />
<MenuItem Header="Paste" cal:Message.Attach="Paste" />
</ContextMenu>
</StackPanel.ContextMenu>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
There may be a much simpler/straightforward approach.
Also worth searching the Caliburn.Micro
discussions, e.g: http://caliburnmicro.codeplex.com/discussions/256163
Upvotes: 2