Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在WPF DataGrid中实现自定义复制和粘贴,该功能在其中没有行时工作_C#_Wpf_Wpfdatagrid_Commandbinding_Routed Commands - Fatal编程技术网

C# 在WPF DataGrid中实现自定义复制和粘贴,该功能在其中没有行时工作

C# 在WPF DataGrid中实现自定义复制和粘贴,该功能在其中没有行时工作,c#,wpf,wpfdatagrid,commandbinding,routed-commands,C#,Wpf,Wpfdatagrid,Commandbinding,Routed Commands,我需要实现一个自定义的复制+剪切+粘贴,以便在WPF应用程序中的网格之间复制数据(不是文本或CSV)。使用标准的ApplicationCommand和定义CommandBinding非常有效,但只有在DataGrid至少包含一行数据并且选中该行时才有效。当没有行或焦点不在任何行上时,所有命令都将被禁用 为了解决这个问题,我尝试调用CommandManager.InvalidateRequestySuggested()并在DataGrid上设置Focusable=true和/或FocusManag

我需要实现一个自定义的复制+剪切+粘贴,以便在WPF应用程序中的网格之间复制数据(不是文本或CSV)。使用标准的ApplicationCommand和定义CommandBinding非常有效,但只有在DataGrid至少包含一行数据并且选中该行时才有效。当没有行或焦点不在任何行上时,所有命令都将被禁用

为了解决这个问题,我尝试调用CommandManager.InvalidateRequestySuggested()并在DataGrid上设置Focusable=true和/或FocusManager.IsFocusScope=true,但DataGrid内部似乎对处理复制/粘贴操作“不感兴趣”,只有它的行重新查询命令CanExecute状态并相应地调用Execute。它还忽略键绑定

如何使DataGrid处理重新查询应用程序命令

请在下面找到我测试问题的示例:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <DataGrid x:Name="TheGrid">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Number" Binding="{Binding}"/>
        </DataGrid.Columns>
        <DataGrid.InputBindings>
            <KeyBinding Key="A" Command="{x:Static ApplicationCommands.New}"/>
        </DataGrid.InputBindings>
        <DataGrid.CommandBindings>
            <CommandBinding Command="{x:Static ApplicationCommands.Paste}" CanExecute="CanPaste" Executed="Paste"/>
            <CommandBinding Command="{x:Static ApplicationCommands.Copy}" CanExecute="CanCopy" Executed="Copy"/>
            <CommandBinding Command="{x:Static ApplicationCommands.New}" CanExecute="CanAddNew" Executed="AddNew"/>
        </DataGrid.CommandBindings>
        <DataGrid.ContextMenu>
            <ContextMenu>
                <MenuItem Command="{x:Static ApplicationCommands.Copy}" Header="Copy"/>
                <MenuItem Command="{x:Static ApplicationCommands.Paste}" Header="Paste"/>
                <MenuItem Command="{x:Static ApplicationCommands.New}" Header="New row"/>
            </ContextMenu>
        </DataGrid.ContextMenu>
    </DataGrid>
</Window>

当ContextMenu打开时,您可以将焦点设置为网格,该网格将启用所有菜单项。这里给出了很好的解释

关于实现粘贴,请参阅SO post

WPF:

<DataGrid x:Name="TheGrid" CanUserAddRows="True" 
          ContextMenuOpening="TheGrid_ContextMenuOpening">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Number" Binding="{Binding}"/>
    </DataGrid.Columns>
    <DataGrid.InputBindings>
        <KeyBinding Key="A" Command="{x:Static ApplicationCommands.New}"/>
    </DataGrid.InputBindings>
    <DataGrid.CommandBindings>                
        <CommandBinding Command="{x:Static ApplicationCommands.Paste}" 
                        CanExecute="CanPaste" Executed="Paste"/>
        <CommandBinding Command="{x:Static ApplicationCommands.Copy}" 
                        CanExecute="CanCopy" Executed="Copy"/>
        <CommandBinding Command="{x:Static ApplicationCommands.New}" 
                        CanExecute="CanAddNew" Executed="AddNew"/>
    </DataGrid.CommandBindings>
    <DataGrid.ContextMenu>
        <ContextMenu>                   
            <MenuItem Command="{x:Static ApplicationCommands.Copy}" Header="Copy"/>
            <MenuItem Command="{x:Static ApplicationCommands.Paste}" Header="Paste"/>
            <MenuItem Command="{x:Static ApplicationCommands.New}" Header="New row"/>
        </ContextMenu>
    </DataGrid.ContextMenu>
</DataGrid>
public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent(); 
        TheGrid.ItemsSource = numbers;
    }

    private void Copy(object sender, ExecutedRoutedEventArgs e)
    {
        Clipboard.SetData(DataFormats.Text, string.Join(",", numbers));
    }

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

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

    private void Paste(object sender, ExecutedRoutedEventArgs e)
    {
        Close();
    }

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

    private void AddNew(object sender, ExecutedRoutedEventArgs e)
    {
        numbers.Add(numbers.Count);
    }

    private readonly ICollection<int> numbers = new ObservableCollection<int>();

    private void TheGrid_ContextMenuOpening(object sender, ContextMenuEventArgs e)
    {
        TheGrid.Focus();
    }

}

C#代码:

<DataGrid x:Name="TheGrid" CanUserAddRows="True" 
          ContextMenuOpening="TheGrid_ContextMenuOpening">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Number" Binding="{Binding}"/>
    </DataGrid.Columns>
    <DataGrid.InputBindings>
        <KeyBinding Key="A" Command="{x:Static ApplicationCommands.New}"/>
    </DataGrid.InputBindings>
    <DataGrid.CommandBindings>                
        <CommandBinding Command="{x:Static ApplicationCommands.Paste}" 
                        CanExecute="CanPaste" Executed="Paste"/>
        <CommandBinding Command="{x:Static ApplicationCommands.Copy}" 
                        CanExecute="CanCopy" Executed="Copy"/>
        <CommandBinding Command="{x:Static ApplicationCommands.New}" 
                        CanExecute="CanAddNew" Executed="AddNew"/>
    </DataGrid.CommandBindings>
    <DataGrid.ContextMenu>
        <ContextMenu>                   
            <MenuItem Command="{x:Static ApplicationCommands.Copy}" Header="Copy"/>
            <MenuItem Command="{x:Static ApplicationCommands.Paste}" Header="Paste"/>
            <MenuItem Command="{x:Static ApplicationCommands.New}" Header="New row"/>
        </ContextMenu>
    </DataGrid.ContextMenu>
</DataGrid>
public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent(); 
        TheGrid.ItemsSource = numbers;
    }

    private void Copy(object sender, ExecutedRoutedEventArgs e)
    {
        Clipboard.SetData(DataFormats.Text, string.Join(",", numbers));
    }

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

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

    private void Paste(object sender, ExecutedRoutedEventArgs e)
    {
        Close();
    }

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

    private void AddNew(object sender, ExecutedRoutedEventArgs e)
    {
        numbers.Add(numbers.Count);
    }

    private readonly ICollection<int> numbers = new ObservableCollection<int>();

    private void TheGrid_ContextMenuOpening(object sender, ContextMenuEventArgs e)
    {
        TheGrid.Focus();
    }

}
公共部分类窗口1:窗口
{
公共窗口1()
{
初始化组件();
grid.ItemsSource=数字;
}
私有无效副本(对象发送方,已执行路由目标)
{
剪贴板.SetData(DataFormats.Text,string.Join(“,”,number));
}
私有void CanCopy(对象发送方,CanExecuteRoutedEventArgs e)
{
e、 CanExecute=true;
}
私有void可以粘贴(对象发送方,CanExecuteRoutedEventArgs e)
{
e、 CanExecute=true;
e、 已处理=正确;
}
私有无效粘贴(对象发送方,已执行路由目标)
{
Close();
}
私有void CanAddNew(对象发送方,CanExecuteRoutedEventArgs e)
{
e、 CanExecute=true;
e、 已处理=正确;
}
私有void AddNew(对象发送方,ExecutedRoutedEventArgs e)
{
number.Add(number.Count);
}
私有只读ICollection编号=新的ObservableCollection();
private void TheGrid_ContextMenuOpening(对象发送方,ContextMenuEventArgs e)
{
TheGrid.Focus();
}
}

这是我的VB.NET版本。它获取一个值,然后将其填充到datagrid中所有选定的单元格中

Private Sub gridpaste(ByVal pasteValue As String)

    Dim rowInd As Integer = Nothing
    Dim colind As Integer = Nothing
    Dim add As Integer = 1

    For Each c As DataGridCellInfo In LineListDataGrid.SelectedCells

        colind = c.Column.DisplayIndex

        rowInd = GetRowIndex(LineListDataGrid, c)

        Try
            LLDB.LineList.Rows(rowInd)(colind) = pasteValue
        Catch err As Exception
            MessageBox.Show(err.Message)
        End Try
    Next

End Sub

   Public Shared Function GetRowIndex(dataGrid As DataGrid, dataGridCellInfo As DataGridCellInfo) As Integer
    Dim dgrow As DataGridRow = DirectCast(dataGrid.ItemContainerGenerator.ContainerFromItem(dataGridCellInfo.Item), DataGridRow)
    If dgrow IsNot Nothing Then
        Return dgrow.GetIndex()
    Else
        Return -1
    End If

End Function

我想这可能是因为行->e.CanExecute=numbers.Count>0;尝试将CanPaste函数中的行更改为e.CanExecute=true;抱歉,如果不关注某一行,则无法启用任何操作,包括ApplicationCommands.New,并且它的e.CanExecute设置始终为true。检查此链接以获取粘贴您的解决方案最有意义,因为上下文菜单会从网格中窃取焦点,并且每次打开上下文菜单时重新获取焦点可能都会解决问题,并且为我做到了这一点。非常感谢。