Сочетание клавиш C + Ctrl не вызывает копирования - PullRequest
4 голосов
/ 18 февраля 2011

Я настроил 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?

Ответы [ 2 ]

11 голосов
/ 18 февраля 2011

Здесь есть пара проблем.

Прежде всего, 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 также определяется в ListBoxlevel, и это единая привязка как для меню правой кнопки мыши, так и для сочетания клавиш.

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;
}
0 голосов
/ 21 февраля 2011

Спасибо Павлову Глазкову за объяснение того, что привязки клавиш и команд должны выполняться на уровне 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());
}
...