C + Ctrl KeyBinding不会导致复制发生

Mat*_*len 5 wpf xaml .net-3.5

我已经设置了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>
Run Code Online (Sandbox Code Playgroud)

如您所见,在模板中,每个模板TextBlock都有一个允许用户复制文本的上下文菜单.这有效.

还有TextBlock一个KeyBindingto ctrl+c和a CommandBinding复制.当我按下ctrl+c方法时KeyCopyLog_Executed没有执行.我已经检查过调试器.

我应该如何绑定密钥TextBlock

Pav*_*kov 12

这里有几个问题.

首先,KeyBindings只有当前聚焦元素位于定义KeyBindings的元素内时才会起作用.在你的情况下,你有一个ListBoxItem焦点,但KeyBindings在子元素上定义 - TextBlock.因此,定义KeyBindings一个TextBlock不会在任何情况下工作,因为一个TextBlock不能接收焦点.

其次,您可能需要知道要复制的内容,因此需要将当前选定的日志项作为参数传递给Copy命令.

此外,如果您ContextMenuTextBlock元素上定义一个元素,只有在右键单击时才会打开它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>
Run Code Online (Sandbox Code Playgroud)

在这里,我们定义了一个KeyBindingListBox自身及指定为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;
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*len 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>
Run Code Online (Sandbox Code Playgroud)

哪里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());
    }
}
Run Code Online (Sandbox Code Playgroud)

并且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());
}
Run Code Online (Sandbox Code Playgroud)