【问题标题】:Copying to clipboard and pasting events复制到剪贴板和粘贴事件
【发布时间】:2015-11-21 11:22:54
【问题描述】:

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

在xml中:

<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 Items Source 设置为用户对象的可观察集合:

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 时,第二个 if 中的代码在 dgKeyDown不执行。

我做错了什么?

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

【问题讨论】:

    标签: c# wpf datagrid clipboard


    【解决方案1】:

    剪贴板有标准格式:

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

    我更喜欢注册我的自定义格式。

    好的, 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 等。 因此,在您的情况下,您可以像这样将 NotACommand 设置为 Copy 内置命令。 在此之后,您可以在我的代码中更改为else if (e.Key == Key.C &amp;&amp; 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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-24
      • 1970-01-01
      • 2017-10-14
      • 1970-01-01
      • 1970-01-01
      • 2011-04-19
      • 2016-09-08
      • 1970-01-01
      相关资源
      最近更新 更多