Вставка таблицы данных WPF

У меня проблемы с вставкой из csv в таблицу данных wpf - я следил за предложениями здесь

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

и код выполняется без проблем - однако кажется, что все новые строки создаются, но только первая строка заполняется данными. Кажется, что данные постоянно перезаписываются, поэтому последний элемент, который находится в данных буфера обмена, заполняется в первой строке, а все остальные строки остаются пустыми. Я знаю, что это проблема с индексом или что-то в этом роде, но я не могу ее отследить.

Также, когда я смотрю на объекты в привязываемой коллекции сетки, ни в одном из них нет данных. Есть ли что-то в 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]);
            }
        }

}


person Jon    schedule 07.11.2010    source источник


Ответы (5)


Спасибо,

Сообщение Vincent очень хорошее, но KlausG добавил в него некоторые исправления, которые также следует учитывать для работы с FrameWork 4.0. Очень важно

Исходное сообщение Винсента на веб-сайте: http://blogs.msdn.com/b/vinsibal/archive/2008/09/25/pasting-content-to-new-rows-on-the-wpf-datagrid.aspx

Примечание. Если вы не можете добавить строку, убедитесь, что у вас есть конструктор по умолчанию для вашего элемента.

Обновлено 06.03.2018 (для поддержки DataGrid со столбцами, переупорядоченными пользователем)

Обновлено 2020-12-03 (согласно исправлению решения Сезара Моригаки и сообщению Антонио Родригеса) Спасибо обоим !!!

использование

<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);

        // Correction according to Cesar Morigaki from SO question: https://stackoverflow.com/questions/4118617/wpf-datagrid-pasting/5436437?noredirect=1#comment115043404_5436437
        var matchesTab = Regex.Matches(line, @"[\r\n\f\v ]*?((?<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;
        }
    }
}
person Eric Ouellet    schedule 25.03.2011
comment
действительно хороший. в основном работает, но иногда я получаю сбой в строке CommitEditCommand.Execute (this, this); и сообщение о сбое: Входная строка не была в правильном формате ... это я получаю, когда использую поле со списком, и если в нем не выбран ни один элемент. Хотя я использовал шаблон MVVM, он будет ожидать чего-то во время вставки. Но попытка решить мою проблему. - person Emil; 17.03.2015
comment
Я добавил свой текущий код. Полагаю, у меня такие же проблемы, как у вас, потому что произошли довольно большие изменения. Надеюсь, это должно сработать. Обратите внимание, что формат CSV иногда имеет разные вкусы (разделитель может измениться:,;, табуляция и т. Д.). На самом деле предоставленный новый код используется в нашем производственном коде и, похоже, работает нормально. Удачи ! - person Eric Ouellet; 17.03.2015
comment
У меня это сработало очень хорошо. Рекомендую проверить решение @Cesar Morigaki на предмет пустых ячеек из excel. - person Antonio Rodríguez; 30.11.2020

Для тех, кто заинтересован - похоже, что-то не так с попыткой столбцов обновить значение привязываемого объекта - возможное преобразование типа данных, поэтому я реализовал это сам, и теперь он работает как шарм.

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]);
            }
        }

}

person Jon    schedule 07.11.2010

Небольшая поправка в CsvHelper.cs из ответа @ eric-ouellet. При копировании из Excel с любой пустой ячейкой сопоставление данных применяется неправильно. Я изменил Regex для метода ParseLineTabSeparated.

public static string[] ParseLineTabSeparated(string line)
{
    var matchesTab = Regex.Matches(line, @"[\r\n\f\v ]*?((?<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;
}
person Cesar Morigaki    schedule 31.08.2018
comment
Спасибо! Работает как шарм. - person GregorMohorko; 12.12.2018

Если я прав, вам также понадобится проверка диапазона для переменной 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 при вставке содержимого с большим количеством столбцов, которое действительно может содержать ваша сетка.

person Rosi    schedule 01.07.2012

https://www.codeproject.com/Articles/1172338/Easy-WPF-Copy-Paste-Excel

Ссылка выше дает функцию «Вставить в DataGrid» с помощью пакета Nuget.

Поддержка типа Bool отсутствует. Мне пришлось скачать исходный код и изменить convert.cs.

 case "System.Boolean": resultado = bool.Parse(valor); break;
 if (tipoDelNulable.Contains("System.Boolean")) resultado = string.IsNullOrEmpty(valor) ? null : (bool?)bool.Parse(valor);
person Istvan Heckl    schedule 05.04.2019