【问题标题】:How do I trigger an event from pasting in DataGrid?如何通过粘贴到 DataGrid 中触发事件?
【发布时间】:2020-07-02 19:14:21
【问题描述】:

我正在尝试从剪贴板中获取文本,将其拆分为一个数组,并在数据网格中为数组中的每个元素创建一个新行。但是,我很难获得触发方法。像这样:

void delivGrid_Keydown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.V &&
            (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
        {
               
            string clipData = System.Windows.Clipboard.GetText();
            string[] clipRows = Regex.Split(clipData, @"\r");
            foreach (var row in clipRows)
            {
                delivGrid.Items.Add(new Deliverable { name = String.Empty, desc = row, rDays = String.Empty });
            }
            //viewModel.Paste()
        }
    }

我无法在 WPF 数据网格的粘贴事件中找到任何内容。有人知道我可以触发此事件以拦截粘贴的方法吗?

【问题讨论】:

    标签: c# wpf events


    【解决方案1】:

    您可以检查DataObject.AddPastingHandler,它允许您为粘贴事件定义一个处理程序,如为 TextBox 显示的here

    问题是粘贴事件只有在控件已经接受它时才会发生: 对于 DataGrid,只有当您尝试粘贴不是您想要实现的可编辑单元格时才会发生这种情况。

    我认为您应该创建一个继承自直接接受粘贴的控件的 CustomControl(例如 TextBox),但您必须重新创建 DataGrid 的一些依赖项(例如 itemsSource)。

    我设置了一个小演示,以便您检查不同的行为:

    MainWindow.xaml:

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <!--Simple DataGrid-->
        <DataGrid x:Name="DataGrid" AutoGenerateColumns="False" MaxWidth="150" Grid.Column="0">
            <DataGrid.Columns>
                <DataGridTextColumn x:Name="Col1" Binding="{Binding Path=BusinessItem1}">
                </DataGridTextColumn>
                <DataGridTextColumn x:Name="Col2" Binding="{Binding Path=BusinessItem2}"/>
            </DataGrid.Columns>
        </DataGrid>
    
        <!--TextBox (so that we can use the copy paste functionnality) modified to show a dataGrid-->
        <TextBox x:Name="TextBoxButActuallyReallyADataGrid" Grid.Column="1">
            <TextBox.Style>
                <Style TargetType="{x:Type TextBox}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate>
                                <Grid>
                                    <DataGrid MinHeight="250" Margin="10" Background="LightBlue" MinWidth="250" x:Name="DataGridForDemoCustomControl" AutoGenerateColumns="False">
                                        <DataGrid.Columns>
                                            <DataGridTextColumn x:Name="CustomCol1" Binding="{Binding Path=BusinessItem1}"/>
                                            <DataGridTextColumn x:Name="CusomCol2" Binding="{Binding Path=BusinessItem2}"/>
                                        </DataGrid.Columns>
                                    </DataGrid>
                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </TextBox.Style>
        </TextBox>
        
        <!--To show the default behavior on a real textBox-->
        <TextBox x:Name="TestTexBox" Text="Default_Text" Grid.Column="2"/>
    </Grid>
    

    MainWindow.xaml.cs:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            //Since it is a demo, I didn't create a ViewModel nor the Bindings but I recommand doing it
            this.GetData();
            this.DataGrid.ItemsSource = this.MyData;
            //Add an handler to the pasting event for the specified dataObject
            //https://docs.microsoft.com/en-gb/dotnet/api/system.windows.dataobject.addpastinghandler?view=netcore-3.1
            DataObject.AddPastingHandler(this.DataGrid, PasteHandler);
            DataObject.AddPastingHandler(TextBoxButActuallyReallyADataGrid, PasteHandlerForTemplatedTextBox);
            DataObject.AddPastingHandler(TestTexBox, PasteHandlerForTextBox);
        }
    
        private void PasteHandlerForTextBox(object sender, DataObjectPastingEventArgs e)
        {
            if (sender is TextBox textbox && e.DataObject.GetDataPresent(typeof(string)))
            {
    
            }
            else
            {
                e.CancelCommand();
            }
    
        }
    
        private void PasteHandlerForTemplatedTextBox(object sender, DataObjectPastingEventArgs e)
        {
            if (sender is TextBox dataGrid && e.DataObject.GetDataPresent(typeof(string)))
            {
    
            }
            else
            {
                e.CancelCommand();
            }
    
        }
    
        private void PasteHandler(object sender, DataObjectPastingEventArgs e)
        {
            if (sender is DataGrid dataGrid && e.DataObject.GetDataPresent(typeof(string)))
            {
                
            }
            else
            {
                e.CancelCommand();
            }
                
        }
    
        private void GetData()
        {
            for (int i = 0; i < 18; i++)
            {
                MyData.Add(new MyRowElement { BusinessItem1 = "text1_" + i.ToString(), BusinessItem2 = "text2_" + i.ToString() });
            }
        }
    
        public ObservableCollection<MyRowElement> MyData { get; private set; } = new ObservableCollection<MyRowElement>();
    }
    
    public class MyRowElement
    {
        public string BusinessItem1 { get; set; }
    
        public string BusinessItem2 { get; set; }
    }
    

    如果您不想创建 CustomControl,您可以像我的示例中那样创建,但您将无法在 codeBehind 中按名称访问 dataGrid。

    【讨论】:

    • 感谢您的详细回复!如果我无法按名称访问 dataGrid,如何操作要显示的数据?我想象我将 ItemsSource 设置为文本框?
    • 如果您使用 MVVM,您可以简单地从 DataGrid 的 ItemsSource 属性绑定到包含 ViewModel 中数据的属性。
    【解决方案2】:

    您应该能够像这样处理PreviewKeyDown

    delivGrid.PreviewKeyDown += (ss, ee) => 
    {
        if (ee.Key == Key.V && (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.R)))
        {
            //...
    
            //escape default behaviour:
            ee.Handled = true;
        }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-23
      • 2013-10-03
      • 1970-01-01
      • 2016-09-21
      • 1970-01-01
      • 2018-07-09
      • 1970-01-01
      • 2011-07-30
      相关资源
      最近更新 更多