我设置了ListBox
,如此:
<ListBox ItemsSource="{Binding Logs, Mode=OneWay}" x:Name="logListView">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=.}">
<TextBlock.InputBindings>
<KeyBinding Key="C"
Modifiers="Ctrl"
Command="Copy"/>
</TextBlock.InputBindings>
<TextBlock.CommandBindings>
<CommandBinding Command="Copy"
Executed="KeyCopyLog_Executed"
CanExecute="CopyLog_CanExecute"/>
</TextBlock.CommandBindings>
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Command="Copy">
<MenuItem.CommandBindings>
<CommandBinding Command="Copy"
Executed="MenuCopyLog_Executed"
CanExecute="CopyLog_CanExecute"/>
</MenuItem.CommandBindings>
</MenuItem>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
如您所见,在模板中,每个TextBlock
都有一个上下文菜单,允许用户复制文本。这很有效。
同样在TextBlock
中有一个KeyBinding
到 ctrl + c 和一个CommandBinding
要复制。当我按 ctrl + c 时,不执行方法KeyCopyLog_Executed
。我已经检查过调试器。
我应该如何将密钥绑定到TextBlock
?
答案 0 :(得分:11)
这里有几个问题。
首先,KeyBindings
仅在当前关注元素位于内部定义KeyBindings的元素时才有效。在您的情况下,您有一个ListBoxItem
焦点,但KeyBindings
是在子元素TextBlock
上定义的。因此,在KeyBindings
上定义TextBlock
在任何情况下都不起作用,因为TextBlock无法获得焦点。
其次,您可能需要知道要复制的内容,因此需要将当前选定的日志项作为参数传递给Copy
命令。
此外,如果您在ContextMenu
元素上定义TextBlock
,只有右键单击TextBlock
时才会打开它。如果单击列表项的任何其他部分,它将无法打开。因此,您需要在列表框项目本身上定义ContextMenu
。
考虑到所有这些,我认为你想要做的事情可以通过以下方式完成:
<ListBox ItemsSource="{Binding Logs, Mode=OneWay}"
x:Name="logListView"
IsSynchronizedWithCurrentItem="True">
<ListBox.InputBindings>
<KeyBinding Key="C"
Modifiers="Ctrl"
Command="Copy"
CommandParameter="{Binding Logs/}" />
</ListBox.InputBindings>
<ListBox.CommandBindings>
<CommandBinding Command="Copy"
Executed="CopyLogExecuted"
CanExecute="CanExecuteCopyLog" />
</ListBox.CommandBindings>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Command="Copy"
CommandParameter="{Binding}" />
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
我们在KeyBinding
本身定义ListBox
,并指定为CommandParameter
当前选中的列表框项(日志条目)。
CommandBinding
也在ListBox
级别定义,它是右键单击菜单和键盘快捷键的单一绑定。
我们在ContextMenu
的样式中定义ListBoxItem
,并将CommandParameter
绑定到此ListBoxItem
(日志条目)所代表的数据项。
DataTemplate
只声明绑定到当前数据项的TextBlock
。
最后,代码隐藏中的Copy
命令只有一个处理程序:
private void CopyLogExecuted(object sender, ExecutedRoutedEventArgs e) {
var logItem = e.Parameter;
// Copy log item to the clipboard
}
private void CanExecuteCopyLog(object sender, CanExecuteRoutedEventArgs e) {
e.CanExecute = true;
}
答案 1 :(得分:0)
感谢Pavlov Glazkov解释密钥和命令绑定需要进入ListBox
级别,而不是项目模板级别。
这是我现在的解决方案:
<ListBox ItemsSource="{Binding Logs, Mode=OneWay}">
<ListBox.InputBindings>
<KeyBinding Key="C"
Modifiers="Ctrl"
Command="Copy"/>
</ListBox.InputBindings>
<ListBox.CommandBindings>
<CommandBinding Command="Copy"
Executed="KeyCopyLog_Executed"
CanExecute="CopyLog_CanExecute"/>
</ListBox.CommandBindings>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=.}">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Command="Copy">
<MenuItem.CommandBindings>
<CommandBinding Command="Copy"
Executed="MenuCopyLog_Executed"
CanExecute="CopyLog_CanExecute"/>
</MenuItem.CommandBindings>
</MenuItem>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
KeyCopyLog_Executed
的位置:
private void KeyCopyLog_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
{
if ((sender as ListBox).SelectedItem != null)
{
LogItem item = (LogItem) (sender as ListBox).SelectedItem;
Clipboard.SetData("Text", item.ToString());
}
}
和MenuCopyLog_Executed
是:
private void MenuCopyLog_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
{
LogItem item = (LogItem) ((sender as MenuItem).TemplatedParent as ContentPresenter).DataContext;
Clipboard.SetData("Text", item.ToString());
}