TreeView的{HierarchicalDataTemplate中的KeyBinding

时间:2016-04-26 12:38:52

标签: c# wpf xaml mvvm treeview

我有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并发送参数?

2 个答案:

答案 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>