【问题标题】:"Drag and Copy" for WPF DataGridWPF DataGrid 的“拖放”
【发布时间】:2017-08-28 13:29:01
【问题描述】:

我的工作场所正在开发一个用于构建常见公司电子表格的内部程序。我们的程序不需要过多的功能,但是我们想要包括的一件事是能够单击一个单元格,将其向上/向下/向左/向右拖动,并将原始单元格的内容复制到用户选择的单元格,就像 Excel 一样。

我寻找一个可靠、明确和上下文相关的答案并没有取得成果。我找到的最接近的东西是this SO question 和关于在数据网格上移动一行的物理位置的文章。该问题的作者没有成功,报告说他们完全跳过了“拖放”实现。

有没有一种合理的方式在按照 MVVM 构建的应用程序中实现此功能?

【问题讨论】:

    标签: c# wpf mvvm datagrid


    【解决方案1】:

    简单的 XAML - 注意添加到数据网格的 SelectionUnit、SelectedCellsChanges 和 Keyup 事件

        <Window x:Class="WpfApp4.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp4"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <DataGrid x:Name="MyGrid" HorizontalAlignment="Left" Height="276" Margin="18,21,0,0" VerticalAlignment="Top" Width="466" SelectionUnit="Cell" SelectedCellsChanged="SelectionChanged" KeyUp="MyGrid_PreviewKeyUp"/>
        </Grid>
    </Window>
    

    一些简单的 C# 代码:

        using System;
        using System.Collections.Generic;
        using System.Windows;
        using System.Windows.Controls;
        using System.Windows.Input;
    
        namespace WpfApp4
        {
            public class MyItems
            {
                public int Col1 { get; set; }
                public int Col2 { get; set; }
                public int Col3 { get; set; }
                public int Col4 { get; set; }
            }
    
            public partial class MainWindow : Window
            {
                // create a source for the datagrid
                public List<MyItems> DataList { get; set; }
    
                // somewhere to hold the selected cells
                IList<DataGridCellInfo> DataGridSelectedCells { get; set; }
    
                public MainWindow()
                {
                    InitializeComponent();
                    DataContext = this;
    
                    DataList = new List<MyItems>()
                    {
                        new MyItems() { Col1=1, Col2=2, Col3=3, Col4=4},
                        new MyItems() { Col1=5, Col2=6, Col3=7, Col4=8},
                        new MyItems() { Col1=9, Col2=10, Col3=11, Col4=12},
                        new MyItems() { Col1=13, Col2=14, Col3=15, Col4=16},
                    };
    
                    MyGrid.ItemsSource = DataList;
    
                }
    
                private void SelectionChanged(object sender, SelectedCellsChangedEventArgs e)
                {
                    DataGridSelectedCells = MyGrid.SelectedCells;
                }
    
                private void MyGrid_PreviewKeyUp(object sender, KeyEventArgs e)
                {
                    // Check your key here (Ctrl D, Ctrl R etc)                  
                    // then loop around your data looking at what is selected
                    // chosing the direction based on what key was pressed       
                    foreach (DataGridCellInfo d in DataGridSelectedCells)
                    {   // get the content of the cell           
                        var cellContent = d.Column.GetCellContent(d.Item);
                        if (cellContent != null)
                        {  // if it's not null try to get the content
                            DataGridCell dc = (DataGridCell)cellContent.Parent;
                            TextBlock tb = (TextBlock)dc.Content;
    
                            // Change the contents of tb.Content here
                            // or dump for debugging
                            Console.WriteLine(tb.Text);
                        }
                    }
                }
            }
    }
    

    用户可以向任何方向拖动单元格,“GridSelectedCells”将仅填充选定的单元格。使用 KeyUp(或其他首选)事件允许用户复制(或使用上下文菜单实现右键单击事件),然后根据需要循环复制数据(向前或向后)。

    虽然它不是一个完整的解决方案,但它应该可以帮助您入门。

    【讨论】:

      【解决方案2】:

      最终解决方案。

      using System.Linq;
      using System.Windows;
      using System.Windows.Controls;
      using System.Windows.Input;
      
      namespace Fatele.Imp.Exp.Application.Applications.Components {
          public class DataGridBehaviour {
            public static readonly DependencyProperty NavLikeProperty = DependencyProperty.RegisterAttached("NavLike",
                  typeof(bool), typeof(DataGridBehaviour), new UIPropertyMetadata(NavLikeChanged));
      
              public static bool GetNavLike(DependencyObject obj) {
                  return (bool) obj.GetValue(NavLikeProperty);
              }
      
              public static void SetNavLike(DependencyObject obj, bool value) {
                  obj.SetValue(NavLikeProperty, value);
              }
      
              private static void NavLikeChanged(object oo, DependencyPropertyChangedEventArgs ee) {
                  var odg = (DataGrid) oo;
                  odg.KeyUp += KeyUp;
              }
      
              private static void KeyUp(object sender, KeyEventArgs e) {
                  var dataGrid = sender as DataGrid;
                  if (dataGrid == null) {
                      return;
                  }
      
                  if (e.Key != Key.LeftCtrl) {
                      return;
                  }
      
                  if (dataGrid.SelectedCells.Count < 2) {
                      return;
                  }
      
                  var firstCell = dataGrid.SelectedCells.First();
                  var propertyInfo = firstCell.Item.GetType().GetProperty(firstCell.Column.SortMemberPath);
                  if (propertyInfo == null) {
                      return;
                  }
      
                  var value1 = propertyInfo.GetValue(firstCell.Item);
                  foreach (var cellInfo in dataGrid.SelectedCells.Skip(1)) {
                      var value2 = propertyInfo.GetValue(cellInfo.Item);
                      if (value2 == null) {
                          propertyInfo.SetValue(cellInfo.Item, value1);
                      }
                  }
              }
          }
      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-07
        • 1970-01-01
        • 1970-01-01
        • 2011-12-14
        • 1970-01-01
        相关资源
        最近更新 更多