复制到剪贴板并粘贴事件

时间:2015-11-21 11:22:55

标签: c# wpf datagrid clipboard

我有一个类用户,其中包含一些string和int类型的字段,我有一个显示这些字段的数据网格,我希望用户能够选择一行并按 CTRL + < kbd> C 将行所代表的对象复制到剪贴板,当用户按下 CTRL + V (当焦点在数据网格上时)将添加数据网格的新行。 代码:

xaml中的

<DataGrid KeyDown="dgKeyDown" SelectionMode="Single" Name="dg1" 
          AutoGenerateColumns="False" CanUserAddRows="True" 
          CopyingRowClipboardContent="dg1Users_CopyingRowClipboardContent">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Name" Width="Auto" Binding="{Binding Name}"/>
        <DataGridTextColumn Header="ID" Width="Auto" Binding="{Binding ID}" />
        <DataGridTextColumn Header="Age" Width="Auto" Binding="{Binding Age}"/>
    </DataGrid.Columns>
</DataGrid>

dg1项目源设置为可观察的用户对象集合:

dg1.ItemsSource = dg1Users;

以及复制和粘贴事件:

private void dg1Users_CopyingRowClipboardContent(object sender, DataGridRowClipboardEventArgs e)
{
    User a = dg1.SelectedItem as User;
    if (a != null)
    {
        Clipboard.Clear();
        Clipboard.SetData("User1", a);
    }
}

private void dgKeyDown(object sender, KeyEventArgs e)
{
    User a = null;
    if (e.Key == Key.V && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
    {
        if(Clipboard.ContainsData("User1"))
        {
            a = (User)Clipboard.GetData("User1");
            dg1Users.Add(a);
        }
    }
}

它不起作用,没有任何反应,使用一些打印语句测试我发现当按下 CTRL + V 时,第二个中的代码如果在dgKeyDown中不执行。

我做错了什么?

注意:我没有使用MVVM模式。

1 个答案:

答案 0 :(得分:1)

剪贴板有标准格式:

  • CSV
  • 文字
  • UnicodeText
  • System.String
  • HTML格式

我更喜欢使用registr我的自定义格式。

行, 1)首先设置[Serializable]属性

[Serializable]
public class User
{
    public string Name { get; set; }

    public string ID { get; set; }

    public string Age { get; set; }
}

2)然后注册格式,(我将其保存到属性以进行调试)

public DataFormat format { get; set; }

format = DataFormats.GetDataFormat(typeof(User).FullName);

3)然后你可以像这样保存你的对象:

User a = dg1.SelectedItem as User;
if (a != null)
{
    IDataObject dataObj = new DataObject();
    dataObj.SetData(format.Name, a, true);
    Clipboard.SetDataObject(dataObj, true);
}

4)你可以像这样追回对象:

User a = null;
IDataObject dataObj = Clipboard.GetDataObject();
if (dataObj != null && dataObj.GetDataPresent(format.Name))
{
    a = dataObj.GetData(format.Name) as User;
    dg1Users.Add(a);
}

5)此外,我们还有问题,我不知道现在如何解决

在你的

private void dg1Users_CopyingRowClipboardContent(object sender, DataGridRowClipboardEventArgs e)
    {
    }

你应该为应对准备数据。例如,在e.ClipboardRowContent中将包含来自所选行的数据的字符串。因此,在g1Users_CopyingRowClipboardContent之后,e.ClipboardRowContent中的所有内容都将被复制。因为你的if(Clipboard.ContainsData("User1"))是假的。因为此时你的剪贴板中存储了字符串。

我更改了代码:

private void dgKeyDown(object sender, KeyEventArgs e)
    {
        User a = null;
        if(e.Key == Key.V && Keyboard.Modifiers == ModifierKeys.Control)
        {
            IDataObject dataObj = Clipboard.GetDataObject();
            if (dataObj !=null && dataObj.GetDataPresent(format.Name))
            {
                a = dataObj.GetData(format.Name) as User;
                dg1Users.Add(a);
            }
        }
        else if (e.Key == Key.B && Keyboard.Modifiers == ModifierKeys.Control)
        {
            User copingUser = dg1.SelectedItem as User;
            if (copingUser != null)
            {
                IDataObject dataObj = new DataObject();
                dataObj.SetData(format.Name, copingUser, true);
                Clipboard.SetDataObject(dataObj, true);
            }
        }
    }

在这种情况下,我可以复制粘贴所选项目

编辑: 因为你不使用MVVM,所以你不要使用ApplicationCommands等。 因此,在您的情况下,您可以像这样为Copy build-in命令设置NotACommand。 在此之后,您可以在我的代码中更改else if (e.Key == Key.C && Keyboard.Modifiers == ModifierKeys.Control)。我测试了它,它可以按你的需要工作。

<DataGrid KeyDown="dgKeyDown" SelectionMode="Single" Name="dg1" 
      AutoGenerateColumns="False" CanUserAddRows="True">
        <DataGrid.InputBindings>
            <KeyBinding Key="C" Modifiers="Control" Command="ApplicationCommands.NotACommand"/>
        </DataGrid.InputBindings>
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name" Width="Auto" Binding="{Binding Name}"/>
            <DataGridTextColumn Header="ID" Width="Auto" Binding="{Binding ID}" />
            <DataGridTextColumn Header="Age" Width="Auto" Binding="{Binding Age}"/>
        </DataGrid.Columns>
    </DataGrid>