C + Ctrl KeyBinding does not cause copying

I installed the ListBox like this:

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

As you can see, in the template, each TextBlock has a context menu that allows the user to copy text. It works.

Also in TextBlock you can copy KeyBinding to ctrl + c and a CommandBinding . When I press ctrl + c , the KeyCopyLog_Executed method KeyCopyLog_Executed . I checked with the debugger.

How do I bind keys to a TextBlock ?

+4
source share
2 answers

Thanks to Pavlov Glazkov for explaining that key and command bindings should go at the ListBox level, and not at the element template level.

This is the solution I have:

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

Where is 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()); } } 

and 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()); } 
0
source

There are a couple of issues here.

First of all, KeyBindings will only work if the currently focused element is inside the element in which KeyBindings are defined. In your case, you have a ListBoxItem focused, but KeyBindings defined for the child - TextBlock . Thus, defining KeyBindings in a TextBlock will not work anyway, since a TextBlock cannot get focus.

Secondly, you probably need to know what you need to copy, so you need to pass the currently selected log item as a parameter to the Copy command.

In addition, if you define the ContextMenu element in the TextBlock element, it will be open only if you right-click on the TextBlock . If you click on any other part of the list item, it will not open. So, you need to define ContextMenu in the list item itself.

Given all this, I believe that you are trying to do this as follows:

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

Here we define the KeyBinding the ListBox itself and specify the CommandParameter ( CommandParameter entry) as the current item in the list.

CommandBinding also defined at the ListBox level, and this is the only binding for both the context menu and quick access.

ContextMenu we define the ListBoxItem style and bind the CommandParameter to the data item represented by this ListBoxItem ( ListBoxItem entry).

DataTemplate simply declares a TextBlock bound to the current data item.

And finally, there is only one handler for the Copy command in the code:

 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; } 
+11
source

Source: https://habr.com/ru/post/1340307/


All Articles