I have a TreeView
. I would like to enable EditLeafCommand
by clicking F2.
Model:
public class Leaf
{
public string LeafName { get; set; }
public bool HasChildren { get; set; }
}
ViewModel of Window:
public MainWindowViewModel{
public ReadOnlyCollection<LeafViewModel> Leafs
{
get { return leafs; }
}
}
ViewModel of TreeView:
public class LeafViewModel : TreeViewItemViewModel
{
public ObservableCollection<TreeViewItemViewModel> Children
{
get { return _children; }
}
public string LeafName { get; set; }
public RelayCommand EditLeafCommand { get; set; }
}
XAML:
<TreeView ItemsSource="{Binding Leafs}">
<TreeView.InputBindings>
<KeyBinding Key="F2" Command="{Binding SelectedItem.EditLeafCommand,
diag:PresentationTraceSources.TraceLevel=High}"/>
</TreeView.InputBindings>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type vm:LeafViewModel}"
ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding LeafName}" IsReadOnly="{Binding IsReadOnlyItem}"
Tag="{Binding DataContext, RelativeSource={RelativeSource Self}}">
<TextBox.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Command="{Binding EditLeafCommand}" CommandParameter="{Binding ALeaf}" Header="Edit" />
</ContextMenu>
</TextBox.ContextMenu>
</TextBox>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
and Output window:
System.Windows.Data Warning: 56 : Created BindingExpression (hash=2683661) for Binding (hash=47044325)
System.Windows.Data Warning: 58 : Path: 'EditLeafCommand'
System.Windows.Data Warning: 60 : BindingExpression (hash=2683661): Default mode resolved to OneWay
System.Windows.Data Warning: 61 : BindingExpression (hash=2683661): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 62 : BindingExpression (hash=2683661): Attach to System.Windows.Input.KeyBinding.Command (hash=29578451)
System.Windows.Data Warning: 64 : BindingExpression (hash=2683661): Use Framework mentor
System.Windows.Data Warning: 67 : BindingExpression (hash=2683661): Resolving source
System.Windows.Data Warning: 69 : BindingExpression (hash=2683661): Framework mentor not found
System.Windows.Data Warning: 65 : BindingExpression (hash=2683661): Resolve source deferred
System.Windows.Data Warning: 95 : BindingExpression (hash=2683661): Got InheritanceContextChanged event from KeyBinding (hash=29578451)
System.Windows.Data Warning: 67 : BindingExpression (hash=2683661): Resolving source
System.Windows.Data Warning: 70 : BindingExpression (hash=2683661): Found data context element: TreeView (hash=11903911) (OK)
System.Windows.Data Warning: 78 : BindingExpression (hash=2683661): Activate with root item MainWindowViewModel (hash=44115416)
System.Windows.Data Warning: 108 : BindingExpression (hash=2683661): At level 0 - for MainWindowViewModel.EditLeafCommand found accessor
System.Windows.Data Error: 40 : BindingExpression path error: 'EditLeafCommand' property not found on 'object' ''MainWindowViewModel' (HashCode=44115416)'. BindingExpression:Path=EditLeafCommand; DataItem='MainWindowViewModel' (HashCode=44115416); target element is 'KeyBinding' (HashCode=29578451); target property is 'Command' (type 'ICommand')
System.Windows.Data Warning: 80 : BindingExpression (hash=2683661): TransferValue - got raw value {DependencyProperty.UnsetValue}
System.Windows.Data Warning: 88 : BindingExpression (hash=2683661): TransferValue - using fallback/default value
System.Windows.Data Warning: 89 : BindingExpression (hash=2683661): TransferValue - using final value
I see this post and it is it is the same question, however, accepted answer does not have any code(I've tried to go through link, however, the offered approach didn't help me)
The error says:
System.Windows.Data Error: 40 :BindingExpression path error: 'EditLeafCommand' property not found on 'object' ''MainWindowViewModel'
But how can I direct to EditLeadViewModel
?
How can I call EditLeafCommand
from LeafViewModel
and send parameter?
Your
MainViewModel
does not have aSelectedItem
property. You need to add this property to your view model and make sure that theINotifyPropertyChanged.PropertyChanged
event is fired when that property changes.You also need to update this property whenever the selected item of the tree view changes. There are various ways to do that. One way is to use the Nuget package System.Windows.Interactivity.WPF. You will have to add a namespace declaration:
Then, inside your tree view XAML element add the following (I'm only showing what to add - keep the rest of your XAML inside the
TreeView
element intact):Note that the
TreeView
element has a name (treeView
) that is used in theCommandParameter
binding in theInvokeCommandAction
element.Also, note that you have to add a
SetSelectedItemCommand
onMainViewModel
. This command should set theSelectedItem
property that I described in my initial paragraph. Here are some code fragments using a genericRelayCommand
:This is the the basic stuff needed to enable your key binding to
SelectedItem.EditLeafCommand
to work. However, you have another problem. YourHierarchicalDataTemplate
defines a tree node to be aTextBox
. When you click on aTextBox
no click is bubbled to theTreeView
and the selection is not changed. My suggestion is that you use a non-interactive representation of each tree node (e.g. aTextBlock
). Then, whenEditLeafCommand
is invoked you put aTextBox
on top allowing the user to edit the node.Andy ONeill has solved this problem. I am really excited by his solution:). I hurry to share this solution with you:
To bind to a command in
LeafViewModel
: