我有TreeView
。我想通过点击 F2 启用EditLeafCommand
。
型号:
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; }
}
}
TreeView的ViewModel:
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>
和输出窗口:
System.Windows.Data警告:56:为绑定创建BindingExpression(hash = 2683661)(hash = 47044325)
System.Windows.Data警告:58:路径:&#39; EditLeafCommand&#39;
System.Windows.Data警告:60:BindingExpression(hash = 2683661):默认模式已解析为OneWay
System.Windows.Data警告:61:BindingExpression(hash = 2683661):解析为PropertyChanged的默认更新触发器
System.Windows.Data警告:62:BindingExpression(hash = 2683661):附加到 System.Windows.Input.KeyBinding.Command(hash = 29578451)
System.Windows.Data警告:64:BindingExpression(hash = 2683661):使用框架导师
System.Windows.Data警告:67:BindingExpression(hash = 2683661):解析源
System.Windows.Data警告:69:BindingExpression(hash = 2683661):找不到框架导师
System.Windows.Data警告:65:BindingExpression(hash = 2683661):解析源延迟
System.Windows.Data警告:95:BindingExpression(hash = 2683661):从KeyBinding获取了InheritanceContextChanged事件(hash = 29578451)
System.Windows.Data警告:67:BindingExpression(hash = 2683661):解析源
System.Windows.Data警告:70:BindingExpression(hash = 2683661):找到数据上下文元素:TreeView(hash = 11903911)(OK)
System.Windows.Data警告:78:BindingExpression(hash = 2683661):使用根项目MainWindowViewModel激活(hash = 44115416)
System.Windows.Data警告:108:BindingExpression(hash = 2683661):在0级 - 对于MainWindowViewModel.EditLeafCommand找到访问者
System.Windows.Data错误:40:BindingExpression路径错误:&#39; EditLeafCommand&#39;在&#39; object&#39;上找不到的属性&#39;&#39; MainWindowViewModel&#39; (的HashCode = 44115416)&#39 ;. BindingExpression:路径= EditLeafCommand;的DataItem =&#39; MainWindowViewModel&#39; (的HashCode = 44115416);目标元素是&#39; KeyBinding&#39; (的HashCode = 29578451);目标财产是&#39; Command&#39; (键入&#39; ICommand&#39;)
System.Windows.Data警告:80:BindingExpression(hash = 2683661):TransferValue - 得到原始值{DependencyProperty.UnsetValue}
System.Windows.Data警告:88:BindingExpression(hash = 2683661):TransferValue - 使用回退/默认值
System.Windows.Data警告:89:BindingExpression(hash = 2683661):TransferValue - 使用最终值
我看到这篇帖子和it is it is the same question,但是,接受的答案没有任何代码(我已尝试通过链接,但是,提供的方法对我没有帮助)
错误说:
System.Windows.Data错误:40:BindingExpression路径错误:&#39; EditLeafCommand&#39;在&#39; object&#39;上找不到的属性&#39;&#39; MainWindowViewModel&#39;
但是如何指向EditLeadViewModel
?
如何从EditLeafCommand
拨打LeafViewModel
并发送参数?
答案 0 :(得分:1)
您的MainViewModel
没有SelectedItem
属性。您需要将此属性添加到视图模型中,并确保在该属性更改时触发INotifyPropertyChanged.PropertyChanged
事件。
每当树视图的选定项发生更改时,您还需要更新此属性。有各种方法可以做到这一点。一种方法是使用Nuget包System.Windows.Interactivity.WPF。您必须添加名称空间声明:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
然后,在树视图中添加以下XAML元素(我只显示要添加的内容 - 保持XAML的其余部分保持在TreeView
元素内完整):
<TreeView Name="treeView" ItemsSource="{Binding Leafs}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged">
<i:InvokeCommandAction Command="{Binding SetSelectedItemCommand, PresentationTraceSources.TraceLevel=High}" CommandParameter="{Binding SelectedItem, ElementName=treeView}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TreeView>
请注意,TreeView
元素的名称(treeView
)在CommandParameter
元素的InvokeCommandAction
绑定中使用。
另请注意,您必须在SetSelectedItemCommand
上添加MainViewModel
。此命令应设置我在初始段落中描述的SelectedItem
属性。以下是一些使用通用RelayCommand
的代码片段:
class MainWindowViewModel {
TreeViewItemViewModel selectedItem;
public MainWindowViewModel() {
SetSelectedItemCommand = new RelayCommand<TreeViewItemViewModel>(SetSelectedItem);
}
public TreeViewItemViewModel SelectedItem {
get { return selectedItem; }
set {
selectedItem = value;
OnPropertyChanged();
}
}
void SetSelectedItem(TreeViewItemViewModel viewModel) {
SelectedItem = viewModel;
}
}
这是启用密钥绑定SelectedItem.EditLeafCommand
所需的基本内容。但是,你有另一个问题。您的HierarchicalDataTemplate
将树节点定义为TextBox
。当您点击TextBox
时,没有任何点击通知TreeView
并且选择不会更改。我的建议是你使用每个树节点的非交互式表示(例如TextBlock
)。然后,当调用EditLeafCommand
时,您将TextBox
置于顶部,允许用户编辑节点。
答案 1 :(得分:0)
Andy ONeill has solved this problem.我很满意他的解决方案:)。我急着和你分享这个解决方案:
绑定到LeafViewModel
中的命令:
<TreeView ItemsSource="{Binding Leafs}" Name="tv">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:LeafViewModel}"
ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<Label VerticalAlignment="Center" FontFamily="WingDings" Content="1"/>
<TextBox Text="{Binding LeafName}" Tag="{Binding DataContext,
RelativeSource={RelativeSource Self}}" Background="Transparent">
<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.InputBindings>
<KeyBinding Key="F2" Command="{Binding SelectedItem.EditLeafCommand, ElementName=tv}"/>
</TreeView.InputBindings>
</TreeView>