2010-11-07 100 views
11

我有从CSV到WPF DataGrid的麻烦粘贴 - 我按照这里的建议WPF数据网格粘贴

http://blogs.msdn.com/b/vinsibal/archive/2008/09/25/pasting-content-to-new-rows-on-the-wpf-datagrid.aspx

和代码exectues没有问题 - 但是,它似乎所有的新行被创建,但只有第一行被填充数据。数据似乎不断被覆盖,以便剪贴板数据中的最后一项填充到第一行,而其他所有行都是空白的。我知道这肯定是一个索引问题,但我无法追查。

另外,当我看看网格的可绑定集合中的对象时,它们都没有任何数据。有没有在OnPastingCellClipboardContent中发生错误的列(可能是数据转换)?

任何想法(见下面的代码)

protected virtual void OnExecutedPaste(object sender, ExecutedRoutedEventArgs args) 
    { 
     // parse the clipboard data 
     List<string[]> rowData = ClipboardHelper.ParseClipboardData(); 
     bool hasAddedNewRow = false; 

     // call OnPastingCellClipboardContent for each cell 
     int minRowIndex = Math.Max(Items.IndexOf(CurrentItem), 0); 
     int maxRowIndex = Items.Count - 1; 
     int minColumnDisplayIndex = (SelectionUnit != DataGridSelectionUnit.FullRow) ? Columns.IndexOf(CurrentColumn) : 0; 
     int maxColumnDisplayIndex = Columns.Count - 1; 

     int rowDataIndex = 0; 
     for (int i = minRowIndex; i <= maxRowIndex && rowDataIndex < rowData.Count; i++, rowDataIndex++) 
     { 
      if (CanUserAddRows && i == maxRowIndex) 
      { 
       // add a new row to be pasted to 
       ICollectionView cv = CollectionViewSource.GetDefaultView(Items); 
       IEditableCollectionView iecv = cv as IEditableCollectionView; 
       if (iecv != null) 
       { 
        hasAddedNewRow = true; 
        iecv.AddNew(); 
        if (rowDataIndex + 1 < rowData.Count) 
        { 
         // still has more items to paste, update the maxRowIndex 
         maxRowIndex = Items.Count - 1; 
        } 
       } 
      } 
      else if (i == maxRowIndex) 
      { 
       continue; 
      } 

      int columnDataIndex = 0; 
      for (int j = minColumnDisplayIndex; j < maxColumnDisplayIndex && columnDataIndex < rowData[rowDataIndex].Length; j++, columnDataIndex++) 
      { 
       DataGridColumn column = ColumnFromDisplayIndex(j); 
       column.OnPastingCellClipboardContent(Items[i], rowData[rowDataIndex][columnDataIndex]); 
      } 
     } 

}

回答

3

对于那些有兴趣 - 那里似乎被什么东西去错列尝试更新绑定对象的值 - 可能数据类型转换,所以我自己实现了这一点,它现在就像一个魅力。

protected virtual void OnExecutedPaste(object sender, ExecutedRoutedEventArgs args) 
    { 
     // parse the clipboard data 
     List<string[]> rowData = ClipboardHelper.ParseClipboardData(); 
     bool hasAddedNewRow = false; 

     // call OnPastingCellClipboardContent for each cell 
     int minRowIndex = Math.Max(Items.IndexOf(CurrentItem), 0); 
     int maxRowIndex = Items.Count - 1; 
     int minColumnDisplayIndex = (SelectionUnit != DataGridSelectionUnit.FullRow) ? Columns.IndexOf(CurrentColumn) : 0; 
     int maxColumnDisplayIndex = Columns.Count - 1; 

     int rowDataIndex = 0; 
     for (int i = minRowIndex; i <= maxRowIndex && rowDataIndex < rowData.Count; i++, rowDataIndex++) 
     { 
      if (CanUserAddRows && i == maxRowIndex) 
      { 
       // add a new row to be pasted to 
       ICollectionView cv = CollectionViewSource.GetDefaultView(Items); 
       IEditableCollectionView iecv = cv as IEditableCollectionView; 
       if (iecv != null) 
       { 
        hasAddedNewRow = true; 
        iecv.AddNew(); 
        if (rowDataIndex + 1 < rowData.Count) 
        { 
         // still has more items to paste, update the maxRowIndex 
         maxRowIndex = Items.Count - 1; 
        } 
       } 
      } 
      else if (i == maxRowIndex) 
      { 
       continue; 
      } 

      int columnDataIndex = 0; 
      for (int j = minColumnDisplayIndex; j < maxColumnDisplayIndex && columnDataIndex < rowData[rowDataIndex].Length; j++, columnDataIndex++) 
      { 
       DataGridColumn column = ColumnFromDisplayIndex(j); 
       string propertyName = ((column as DataGridBoundColumn).Binding as Binding).Path.Path; 
       object item = Items[i]; 
       object value = rowData[rowDataIndex][columnDataIndex]; 
       PropertyInfo pi = item.GetType().GetProperty(propertyName); 
       if (pi != null) 
       { 
        object convertedValue = Convert.ChangeType(value, pi.PropertyType); 
        item.GetType().GetProperty(propertyName).SetValue(item, convertedValue, null);      
       } 
       //column.OnPastingCellClipboardContent(item, rowData[rowDataIndex][columnDataIndex]); 
      } 
     } 

}

12

感谢,

员额由文森特但KlausG加在它的一些修正也应当考虑与框架4.0的工作非常好。很重要的

原始网站后从文森特:http://blogs.msdn.com/b/vinsibal/archive/2008/09/25/pasting-content-to-new-rows-on-the-wpf-datagrid.aspx

注意:如果你不能添加一行确保你有你的项目一个默认的构造。

更新2018年3月6日(以支持在DataGrid中列由用户重新排序)

使用

<myControl:CustomDataGrid ... 

CustomDataGrid

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Reflection; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Input; 

namespace HQ.Wpf.Util.MyControl 
{ 
    public class CustomDataGrid : DataGrid 
    { 
     public event ExecutedRoutedEventHandler ExecutePasteEvent; 
     public event CanExecuteRoutedEventHandler CanExecutePasteEvent; 

     // ****************************************************************** 
     static CustomDataGrid() 
     { 
      CommandManager.RegisterClassCommandBinding(
       typeof(CustomDataGrid), 
       new CommandBinding(ApplicationCommands.Paste, 
        new ExecutedRoutedEventHandler(OnExecutedPasteInternal), 
        new CanExecuteRoutedEventHandler(OnCanExecutePasteInternal))); 
     } 

     // ****************************************************************** 
     #region Clipboard Paste 

     // ****************************************************************** 
     private static void OnCanExecutePasteInternal(object target, CanExecuteRoutedEventArgs args) 
     { 
      ((CustomDataGrid)target).OnCanExecutePaste(target, args); 
     } 

     // ****************************************************************** 
     /// <summary> 
     /// This virtual method is called when ApplicationCommands.Paste command query its state. 
     /// </summary> 
     /// <param name="args"></param> 
     protected virtual void OnCanExecutePaste(object target, CanExecuteRoutedEventArgs args) 
     { 
      if (CanExecutePasteEvent != null) 
      { 
       CanExecutePasteEvent(target, args); 
       if (args.Handled) 
       { 
        return; 
       } 
      } 

      args.CanExecute = CurrentCell != null; 
      args.Handled = true; 
     } 

     // ****************************************************************** 
     private static void OnExecutedPasteInternal(object target, ExecutedRoutedEventArgs args) 
     { 
      ((CustomDataGrid)target).OnExecutedPaste(target, args); 
     } 

     // ****************************************************************** 
     /// <summary> 
     /// This virtual method is called when ApplicationCommands.Paste command is executed. 
     /// </summary> 
     /// <param name="target"></param> 
     /// <param name="args"></param> 
     protected virtual void OnExecutedPaste(object target, ExecutedRoutedEventArgs args) 
     { 
      if (ExecutePasteEvent != null) 
      { 
       ExecutePasteEvent(target, args); 
       if (args.Handled) 
       { 
        return; 
       } 
      } 

      // parse the clipboard data   [row][column] 
      List<string[]> clipboardData = HQ.Util.General.Clipboard.ClipboardHelper2.ParseClipboardData(); 

      bool hasAddedNewRow = false; 

      Debug.Print(">>> DataGrid Paste: >>>"); 
#if DEBUG 
      StringBuilder sb = new StringBuilder(); 
#endif 
      int minRowIndex = Items.IndexOf(CurrentItem); 
      int maxRowIndex = Items.Count - 1; 
      int startIndexOfDisplayCol = (SelectionUnit != DataGridSelectionUnit.FullRow) ? CurrentColumn.DisplayIndex : 0; 
      int clipboardRowIndex = 0; 
      for (int i = minRowIndex; i <= maxRowIndex && clipboardRowIndex < clipboardData.Count; i++, clipboardRowIndex++) 
      { 
       if (i < this.Items.Count) 
       { 
        CurrentItem = Items[i]; 

        BeginEditCommand.Execute(null, this); 

        int clipboardColumnIndex = 0; 
        for (int j = startIndexOfDisplayCol; clipboardColumnIndex < clipboardData[clipboardRowIndex].Length; j++, clipboardColumnIndex++) 
        { 
         // DataGridColumn column = ColumnFromDisplayIndex(j); 
         DataGridColumn column = null; 
         foreach (DataGridColumn columnIter in this.Columns) 
         { 
          if (columnIter.DisplayIndex == j) 
          { 
           column = columnIter; 
           break; 
          } 
         } 

         column?.OnPastingCellClipboardContent(Items[i], clipboardData[clipboardRowIndex][clipboardColumnIndex]); 

#if DEBUG 
         sb.AppendFormat("{0,-10}", clipboardData[clipboardRowIndex][clipboardColumnIndex]); 
         sb.Append(" - "); 
#endif 
        } 

        CommitEditCommand.Execute(this, this); 
        if (i == maxRowIndex) 
        { 
         maxRowIndex++; 
         hasAddedNewRow = true; 
        } 
       } 

       Debug.Print(sb.ToString()); 
#if DEBUG 
       sb.Clear(); 
#endif 
      } 

      // update selection 
      if (hasAddedNewRow) 
      { 
       UnselectAll(); 
       UnselectAllCells(); 

       CurrentItem = Items[minRowIndex]; 

       if (SelectionUnit == DataGridSelectionUnit.FullRow) 
       { 
        SelectedItem = Items[minRowIndex]; 
       } 
       else if (SelectionUnit == DataGridSelectionUnit.CellOrRowHeader || 
         SelectionUnit == DataGridSelectionUnit.Cell) 
       { 
        SelectedCells.Add(new DataGridCellInfo(Items[minRowIndex], Columns[startIndexOfDisplayCol])); 

       } 
      } 
     } 

     // ****************************************************************** 
     /// <summary> 
     ///  Whether the end-user can add new rows to the ItemsSource. 
     /// </summary> 
     public bool CanUserPasteToNewRows 
     { 
      get { return (bool)GetValue(CanUserPasteToNewRowsProperty); } 
      set { SetValue(CanUserPasteToNewRowsProperty, value); } 
     } 

     // ****************************************************************** 
     /// <summary> 
     ///  DependencyProperty for CanUserAddRows. 
     /// </summary> 
     public static readonly DependencyProperty CanUserPasteToNewRowsProperty = 
      DependencyProperty.Register("CanUserPasteToNewRows", 
             typeof(bool), typeof(CustomDataGrid), 
             new FrameworkPropertyMetadata(true, null, null)); 

     // ****************************************************************** 
     #endregion Clipboard Paste 

     private void SetGridToSupportManyEditEitherWhenValidationErrorExists() 
     { 
      this.Items.CurrentChanged += Items_CurrentChanged; 


      //Type DatagridType = this.GetType().BaseType; 
      //PropertyInfo HasCellValidationProperty = DatagridType.GetProperty("HasCellValidationError", BindingFlags.NonPublic | BindingFlags.Instance); 
      //HasCellValidationProperty. 
     } 

     void Items_CurrentChanged(object sender, EventArgs e) 
     { 
      //this.Items[0]. 
      //throw new NotImplementedException(); 
     } 

     // ****************************************************************** 
     private void SetGridWritable() 
     { 
      Type DatagridType = this.GetType().BaseType; 
      PropertyInfo HasCellValidationProperty = DatagridType.GetProperty("HasCellValidationError", BindingFlags.NonPublic | BindingFlags.Instance); 
      if (HasCellValidationProperty != null) 
      { 
       HasCellValidationProperty.SetValue(this, false, null); 
      } 
     } 

     // ****************************************************************** 
     public void SetGridWritableEx() 
     { 
      BindingFlags bindingFlags = BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Instance; 
      PropertyInfo cellErrorInfo = this.GetType().BaseType.GetProperty("HasCellValidationError", bindingFlags); 
      PropertyInfo rowErrorInfo = this.GetType().BaseType.GetProperty("HasRowValidationError", bindingFlags); 
      cellErrorInfo.SetValue(this, false, null); 
      rowErrorInfo.SetValue(this, false, null); 
     } 

     // ****************************************************************** 
    } 
} 

另外:剪贴板助手:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Diagnostics; 
using System.Windows; 
using System.IO; 

namespace HQ.Util.General.Clipboard 
{ 
    public static class ClipboardHelper 
    { 
     public delegate string[] ParseFormat(string value); 

     public static List<string[]> ParseClipboardData() 
     { 
      List<string[]> clipboardData = null; 
      object clipboardRawData = null; 
      ParseFormat parseFormat = null; 

      // get the data and set the parsing method based on the format 
      // currently works with CSV and Text DataFormats    
      IDataObject dataObj = System.Windows.Clipboard.GetDataObject(); 
      if ((clipboardRawData = dataObj.GetData(DataFormats.CommaSeparatedValue)) != null) 
      { 
       parseFormat = ParseCsvFormat; 
      } 
      else if((clipboardRawData = dataObj.GetData(DataFormats.Text)) != null) 
      { 
       parseFormat = ParseTextFormat; 
      } 

      if (parseFormat != null) 
      { 
       string rawDataStr = clipboardRawData as string; 

       if (rawDataStr == null && clipboardRawData is MemoryStream) 
       { 
        // cannot convert to a string so try a MemoryStream 
        MemoryStream ms = clipboardRawData as MemoryStream; 
        StreamReader sr = new StreamReader(ms); 
        rawDataStr = sr.ReadToEnd(); 
       } 
       Debug.Assert(rawDataStr != null, string.Format("clipboardRawData: {0}, could not be converted to a string or memorystream.", clipboardRawData)); 

       string[] rows = rawDataStr.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); 
       if (rows != null && rows.Length > 0) 
       { 
        clipboardData = new List<string[]>(); 
        foreach (string row in rows) 
        { 
         clipboardData.Add(parseFormat(row)); 
        } 
       } 
       else 
       { 
        Debug.WriteLine("unable to parse row data. possibly null or contains zero rows."); 
       } 
      } 

      return clipboardData; 
     } 

     public static string[] ParseCsvFormat(string value) 
     { 
      return ParseCsvOrTextFormat(value, true); 
     } 

     public static string[] ParseTextFormat(string value) 
     { 
      return ParseCsvOrTextFormat(value, false); 
     } 

     private static string[] ParseCsvOrTextFormat(string value, bool isCSV) 
     { 
      List<string> outputList = new List<string>(); 

      char separator = isCSV ? ',' : '\t'; 
      int startIndex = 0; 
      int endIndex = 0; 

      for (int i = 0; i < value.Length; i++) 
      { 
       char ch = value[i]; 
       if (ch == separator) 
       { 
        outputList.Add(value.Substring(startIndex, endIndex - startIndex)); 

        startIndex = endIndex + 1; 
        endIndex = startIndex; 
       } 
       else if (ch == '\"' && isCSV) 
       { 
        // skip until the ending quotes 
        i++; 
        if (i >= value.Length) 
        { 
         throw new FormatException(string.Format("value: {0} had a format exception", value)); 
        } 
        char tempCh = value[i]; 
        while (tempCh != '\"' && i < value.Length) 
         i++; 

        endIndex = i; 
       } 
       else if (i + 1 == value.Length) 
       { 
        // add the last value 
        outputList.Add(value.Substring(startIndex)); 
        break; 
       } 
       else 
       { 
        endIndex++; 
       } 
      } 

      return outputList.ToArray(); 
     } 
    } 
} 

个CsvHelper.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text.RegularExpressions; 
using MoreLinq; // http://stackoverflow.com/questions/15265588/how-to-find-item-with-max-value-using-linq 

namespace HQ.Util.General.CSV 
{ 
    public class CsvHelper 
    { 
     public static Dictionary<LineSeparator, Func<string, string[]>> DictionaryOfLineSeparatorAndItsFunc = new Dictionary<LineSeparator, Func<string, string[]>>(); 

     static CsvHelper() 
     { 
      DictionaryOfLineSeparatorAndItsFunc[LineSeparator.Unknown] = ParseLineNotSeparated; 
      DictionaryOfLineSeparatorAndItsFunc[LineSeparator.Tab] = ParseLineTabSeparated; 
      DictionaryOfLineSeparatorAndItsFunc[LineSeparator.Semicolon] = ParseLineSemicolonSeparated; 
      DictionaryOfLineSeparatorAndItsFunc[LineSeparator.Comma] = ParseLineCommaSeparated; 
     } 

     // ****************************************************************** 
     public enum LineSeparator 
     { 
      Unknown = 0, 
      Tab, 
      Semicolon, 
      Comma 
     } 

     // ****************************************************************** 
     public static LineSeparator GuessCsvSeparator(string oneLine) 
     { 
      List<Tuple<LineSeparator, int>> listOfLineSeparatorAndThereFirstLineSeparatedValueCount = new List<Tuple<LineSeparator, int>>(); 

      listOfLineSeparatorAndThereFirstLineSeparatedValueCount.Add(new Tuple<LineSeparator, int>(LineSeparator.Tab, CsvHelper.ParseLineTabSeparated(oneLine).Count())); 
      listOfLineSeparatorAndThereFirstLineSeparatedValueCount.Add(new Tuple<LineSeparator, int>(LineSeparator.Semicolon, CsvHelper.ParseLineSemicolonSeparated(oneLine).Count())); 
      listOfLineSeparatorAndThereFirstLineSeparatedValueCount.Add(new Tuple<LineSeparator, int>(LineSeparator.Comma, CsvHelper.ParseLineCommaSeparated(oneLine).Count())); 

      Tuple<LineSeparator, int> bestBet = listOfLineSeparatorAndThereFirstLineSeparatedValueCount.MaxBy((n)=>n.Item2); 

      if (bestBet != null && bestBet.Item2 > 1) 
      { 
       return bestBet.Item1; 
      } 

      return LineSeparator.Unknown; 
     } 

     // ****************************************************************** 
     public static string[] ParseLineCommaSeparated(string line) 
     { 
      // CSV line parsing : From "jgr4" in http://www.kimgentes.com/worshiptech-web-tools-page/2008/10/14/regex-pattern-for-parsing-csv-files-with-embedded-commas-dou.html 
      var matches = Regex.Matches(line, @"\s?((?<x>(?=[,]+))|""(?<x>([^""]|"""")+)""|""(?<x>)""|(?<x>[^,]+)),?", 
             RegexOptions.ExplicitCapture); 

      string[] values = (from Match m in matches 
           select m.Groups["x"].Value.Trim().Replace("\"\"", "\"")).ToArray(); 

      return values; 
     } 

     // ****************************************************************** 
     public static string[] ParseLineTabSeparated(string line) 
     { 
      var matchesTab = Regex.Matches(line, @"\s?((?<x>(?=[\t]+))|""(?<x>([^""]|"""")+)""|""(?<x>)""|(?<x>[^\t]+))\t?", 
          RegexOptions.ExplicitCapture); 

      string[] values = (from Match m in matchesTab 
           select m.Groups["x"].Value.Trim().Replace("\"\"", "\"")).ToArray(); 

      return values; 
     } 

     // ****************************************************************** 
     public static string[] ParseLineSemicolonSeparated(string line) 
     { 
      // CSV line parsing : From "jgr4" in http://www.kimgentes.com/worshiptech-web-tools-page/2008/10/14/regex-pattern-for-parsing-csv-files-with-embedded-commas-dou.html 
      var matches = Regex.Matches(line, @"\s?((?<x>(?=[;]+))|""(?<x>([^""]|"""")+)""|""(?<x>)""|(?<x>[^;]+));?", 
             RegexOptions.ExplicitCapture); 

      string[] values = (from Match m in matches 
           select m.Groups["x"].Value.Trim().Replace("\"\"", "\"")).ToArray(); 

      return values; 
     } 

     // ****************************************************************** 
     public static string[] ParseLineNotSeparated(string line) 
     { 
      string [] lineValues = new string[1]; 
      lineValues[0] = line; 
      return lineValues; 
     } 

     // ****************************************************************** 
     public static List<string[]> ParseText(string text) 
     { 
      string[] lines = text.Split(new string[] { "\r\n" }, StringSplitOptions.None); 
      return ParseString(lines); 
     } 

     // ****************************************************************** 
     public static List<string[]> ParseString(string[] lines) 
     { 
      List<string[]> result = new List<string[]>(); 

      LineSeparator lineSeparator = LineSeparator.Unknown; 
      if (lines.Any()) 
      { 
       lineSeparator = GuessCsvSeparator(lines[0]); 
      } 

      Func<string, string[]> funcParse = DictionaryOfLineSeparatorAndItsFunc[lineSeparator]; 

      foreach (string line in lines) 
      { 
       if (string.IsNullOrWhiteSpace(line)) 
       { 
        continue; 
       } 

       result.Add(funcParse(line)); 
      } 

      return result; 
     } 

     // ****************************************************************** 
    } 
} 

ClipboardHelper2.cs

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Runtime.InteropServices; 
using System.Text.RegularExpressions; 
using System.Windows; 
using System.IO; 
using System.Linq; 
using System.Windows.Forms.VisualStyles; 
using HQ.Util.General.CSV; 

namespace HQ.Util.General.Clipboard 
{ 
    // Uses Clipboard in WPF (PresentationCore.dll in v4 of the framework) 
    public static class ClipboardHelper2 
    { 
     public delegate string[] ParseFormat(string value); 

     public static List<string[]> ParseClipboardData() 
     { 
      List<string[]> clipboardData = new List<string[]>(); 

      // get the data and set the parsing method based on the format 
      // currently works with CSV and Text DataFormats    
      IDataObject dataObj = System.Windows.Clipboard.GetDataObject(); 

      if (dataObj != null) 
      { 
       string[] formats = dataObj.GetFormats(); 
       if (formats.Contains(DataFormats.CommaSeparatedValue)) 
       { 
        string clipboardString = (string)dataObj.GetData(DataFormats.CommaSeparatedValue); 
        { 
         // EO: Subject to error when a CRLF is included as part of the data but it work for the moment and I will let it like it is 
         // WARNING ! Subject to errors 
         string[] lines = clipboardString.Split(new string[] { "\r\n" }, StringSplitOptions.None); 

         string[] lineValues; 
         foreach (string line in lines) 
         { 
          lineValues = CsvHelper.ParseLineCommaSeparated(line); 
          if (lineValues != null) 
          { 
           clipboardData.Add(lineValues); 
          } 
         } 
        } 
       } 
       else if (formats.Contains(DataFormats.Text)) 
       { 
        string clipboardString = (string)dataObj.GetData(DataFormats.Text); 
        clipboardData = CsvHelper.ParseText(clipboardString); 
       } 
      } 

      return clipboardData; 
     } 
    } 
} 
+0

真的很不错。主要是工程,但有时我得到一个崩溃的行CommitEditCommand。执行(在此,这一点);并且崩溃消息是“输入字符串格式不正确”。当我使用组合框并且没有选择元素时,我会得到这个结果。尽管我使用了MVVM模板,但它在粘贴时会有所期待。但试一试可以解决我的问题。 – batmaci 2015-03-17 14:52:57

+0

我添加了我的当前代码。我想我有像你这样的问题,因为有很大的变化。我希望这个应该有效。请注意,CSV格式有时会有不同的风格(分隔符可能会更改:“,”“;”,选项卡等)。实际上,我们的生产代码中使用了提供的新代码,似乎可以正常工作。祝你好运 ! – 2015-03-17 17:33:49

0

如果我是正确的,你也应该需要变量j一系列检查:

  for (int j = minColumnDisplayIndex; j <= maxColumnDisplayIndex && columnDataIndex < rowData[rowDataIndex].Length; j++, columnDataIndex++) 
      { 
       if (j == maxColumnDisplayIndex) 
        continue; 
       DataGridColumn column = ColumnFromDisplayIndex(j); 
       column.OnPastingCellClipboardContent(Items[i], rowData[rowDataIndex][columnDataIndex]); 
      } 

否则,你得到一个ArgumentOutOfRangeException当将内容粘贴到网格实际可以容纳的更多列上。