문제

I have a ListBox of TextBlock(s) that I would like the end user to be able to copy the text from the display and then they can paste it to where they like. I am able to get a single line copy with the right click-> copy, and with a user's ctrl+c key press. I am also able to get a multiple line copy with a user's ctrl+c key press. I would like to be able to do a multiple line copy with the right click->copy feature as well as from a Menu drop down call.

My ListBox:

    <!--Progress Window-->
    <ListBox x:Name="Progress_Window" ItemsSource="{Binding _displayString}" ScrollViewer.ScrollChanged="Progress_Window_ScrollChanged" KeyDown="Progress_Window_KeyDown" SelectionMode="Extended">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding _string}" Foreground="{Binding _color}" FontSize="{Binding _fontSize}">

                    <TextBlock.ContextMenu>
                        <ContextMenu>
                            <MenuItem Command="Copy">
                                <MenuItem.CommandBindings>
                                    <CommandBinding Command="ApplicationCommands.Copy" CanExecute="RightClickCopyCmdCanExecute" Executed="RightClickCopyCmdExecuted" />
                                </MenuItem.CommandBindings>
                            </MenuItem>
                        </ContextMenu>
                    </TextBlock.ContextMenu>

                </TextBlock>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

The code behind:

    [DllImport("user32.dll", SetLastError = true)]
    static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);


    [DllImport("kernel32.dll")]
    static extern bool GenerateConsoleCtrlEvent(uint dwCtrlEvent, uint dwProcessGroupId);


    public const int KEYEVENTF_EXTENDEDKEY = 0x0001; //Key down flag
    public const int KEYEVENTF_KEYUP = 0x0002; //Key up flag
    public const int VK_LCONTROL = 0xA3;   //0xA2; //Left Control key code
    public const int C = 0x43; //A Control key code


    private void Progress_Window_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.C && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
        {
            try
            {
                ListBox lb = (ListBox)(sender);

                string collectedText = "";

                foreach (DisplayData dd in lb.SelectedItems)
                {
                    collectedText += dd._string + "\r\n";
                }

                if (lb.SelectedItems != null)
                {
                    Clipboard.SetText(collectedText);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }


    private void RightClickCopyCmdExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        MenuItem mi = (MenuItem)sender;
        DisplayData selected = (DisplayData)mi.DataContext;

        if (selected != null)
        {
            Clipboard.SetText(selected._string);
        }
    }


    private void RightClickCopyCmdCanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
    }


    public void CallKeyDown()
    {
        //Progress_Window.Focus();

        //// Hold Control down and press C
        //keybd_event(VK_LCONTROL, 0, 0, 0);
        //keybd_event(C, 0, 0, 0);
        //keybd_event(C, 0, KEYEVENTF_KEYUP, 0);
        //keybd_event(VK_LCONTROL, 0, KEYEVENTF_KEYUP, 0);

        System.Windows.Forms.SendKeys.SendWait("^{c}");

        var key = Key.C;             // Key to send            
        var target = Progress_Window;               // Target element
        var routedEvent = Keyboard.KeyDownEvent;    // Event to send

        target.RaiseEvent(new KeyEventArgs(Keyboard.PrimaryDevice, PresentationSource.FromVisual(target), 0, key) { RoutedEvent = routedEvent });
    }
}

From the Menu drop down:

<Grid>
    <Menu>
        <!--File-->
        <MenuItem Header="_File">
            <MenuItem Header="_Close" Command="{Binding Close}" />
        </MenuItem>

        <!--Edit-->
        <MenuItem Header="_Edit">
            <MenuItem Header="_Copy     Ctrl+C" Command="{Binding CtrlC}" />
        </MenuItem>

CtrlC command calls an Action that triggers CallKeyDown().

I have tried to move my ContextMenu from the TextBlock to the ListBox, but that gave me the DataContext of my ViewModel instead of giving me the _displayString data.

As you can see in CallKeyDown() I am trying to simulate a ctrl+c key press from code behind with no success. I don't know if that is the best approach to this problem. I also tried to use SendKeys.Send("^{c}") but that only works with Window Forms.

도움이 되었습니까?

해결책

I just need to copy my code in RightClickCopyCmdExecuted into CallKeyDown(), and all is well. Then I will call CallKeyDown from RightClickCopyCmdExecuted.

I got the multiple lines for the right click->copy on the list box. So my ListBox becomes:

    <!--Progress Window-->
    <ListBox x:Name="Progress_Window" ItemsSource="{Binding _displayString}" ScrollViewer.ScrollChanged="Progress_Window_ScrollChanged" KeyDown="Progress_Window_KeyDown" SelectionMode="Extended">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding _string}" Foreground="{Binding _color}" FontSize="{Binding _fontSize}" />
            </DataTemplate>
        </ListBox.ItemTemplate>

        <ListBox.ContextMenu>
            <ContextMenu>
                <MenuItem Command="Copy">
                    <MenuItem.CommandBindings>
                        <CommandBinding Command="ApplicationCommands.Copy" CanExecute="RightClickCopyCmdCanExecute" Executed="RightClickCopyCmdExecuted" />
                    </MenuItem.CommandBindings>
                </MenuItem>
            </ContextMenu>
        </ListBox.ContextMenu>
    </ListBox>

and the code behind becomes:

    private void RightClickCopyCmdExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        string collectedText = "";

        foreach (DisplayData dd in Progress_Window.SelectedItems)
        {
            collectedText += dd._string + "\r\n";
        }

        if (Progress_Window.SelectedItems != null)
        {
            Clipboard.SetText(collectedText);
        }
    }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top