Search code examples
c#wpflistboxclipboard

WPF listbox copy to clipboard


I am trying to copy a standard WPF ListBox selected Item (displayed) text to clipboard on CTRL+C. Is there any simple way to achieve this. If it is something that works for all the listboxes in the app.


Solution

  • As you're in WPF so you could try the attached behaviours
    First you need a class like this:

    public static class ListBoxBehaviour
    {
        public static readonly DependencyProperty AutoCopyProperty = DependencyProperty.RegisterAttached("AutoCopy",
            typeof(bool), typeof(ListBoxBehaviour), new UIPropertyMetadata(AutoCopyChanged));
    
        public static bool GetAutoCopy(DependencyObject obj_)
        {
            return (bool) obj_.GetValue(AutoCopyProperty);
        }
    
        public static void SetAutoCopy(DependencyObject obj_, bool value_)
        {
            obj_.SetValue(AutoCopyProperty, value_);
        }
    
        private static void AutoCopyChanged(DependencyObject obj_, DependencyPropertyChangedEventArgs e_)
        {
            var listBox = obj_ as ListBox;
            if (listBox != null)
            {
                if ((bool)e_.NewValue)
                {
                    ExecutedRoutedEventHandler handler =
                        (sender_, arg_) =>
                        {
                            if (listBox.SelectedItem != null)
                            {
                                //Copy what ever your want here
                                Clipboard.SetDataObject(listBox.SelectedItem.ToString());
                            }
                        };
    
                    var command = new RoutedCommand("Copy", typeof (ListBox));
                    command.InputGestures.Add(new KeyGesture(Key.C, ModifierKeys.Control, "Copy"));
                    listBox.CommandBindings.Add(new CommandBinding(command, handler));
                }
            }
        }
    }
    


    Then you have the XAML like this

    <ListBox sample:ListBoxBehaviour.AutoCopy="True">
      <ListBox.Items>
        <ListBoxItem Content="a"/>
        <ListBoxItem Content="b"/>
      </ListBox.Items>
    </ListBox>
    


    Updates: For the simplest case, you can access the text in the below way:

    private static string GetListBoxItemText(ListBox listBox_, object item_)
    {
      var listBoxItem = listBox_.ItemContainerGenerator.ContainerFromItem(item_)
                        as ListBoxItem;
      if (listBoxItem != null)
      {
        var textBlock = FindChild<TextBlock>(listBoxItem);
        if (textBlock != null)
        {
          return textBlock.Text;
        }
      }
      return null;
    }
    
    GetListBoxItemText(myListbox, myListbox.SelectedItem)
    FindChild<T> is a function to find a child of type T of a DependencyObject
    

    But just like the ListBoxItem could be bound to object, the ItemTemplate could be different as well, so you can't rely on it in real projects.