Мы реализовали решение для копирования и вставки данных в Datagrid. Там, где мы получили решение, оно очень хорошо работает для того, что мы пытаемся сделать. Однако мы искали способы ускорить фактическую вставку данных: для небольших объемов данных вставка происходит довольно быстро, но как только набор данных начинает становиться немного больше, мы видим, что скорость замедляется. Итак, я просто ищу способ ускорить функцию вставки, или я знаю, что представления списков иногда в некоторых отношениях работают быстрее, просто не могу придумать, как использовать этот код для разработки нового представления списка копирования/вставки. Если у вас есть предложения, дайте мне знать, спасибо
public class CustomDataGrid : DataGrid
{
public event ExecutedRoutedEventHandler ExecutePasteEvent;
public event CanExecuteRoutedEventHandler CanExecutePasteEvent;
public event CanExecuteRoutedEventHandler CanExecuteDeleteEvent;
private bool ctrlPressed = false;
static CustomDataGrid()
{
CommandManager.RegisterClassCommandBinding(
typeof(CustomDataGrid),
new CommandBinding(ApplicationCommands.Paste,
new ExecutedRoutedEventHandler(OnExecutedPasteInternal),
new CanExecuteRoutedEventHandler(OnCanExecutePasteInternal)));
CommandManager.RegisterClassCommandBinding(
typeof(CustomDataGrid),
new CommandBinding(ApplicationCommands.Delete,
new ExecutedRoutedEventHandler(OnExecutedDeleteInternal),
new CanExecuteRoutedEventHandler(OnCanExecuteDeleteInternal)));
}
public CustomDataGrid()
{
PreviewKeyDown += OnPreviewKeyDown;
PreviewKeyUp += OnPreviewKeyUp;
}
#region Selecting all cells in the clicked column
protected override void OnSorting(DataGridSortingEventArgs eventArgs)
{
SelectColumnCells(eventArgs.Column);
//base.OnSorting(eventArgs);
eventArgs.Handled = true;
}
private void OnPreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)
{
ctrlPressed = true;
}
}
private void OnPreviewKeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)
{
ctrlPressed = false;
}
}
private void SelectColumnCells(DataGridColumn column)
{
if (!ctrlPressed)
{
// Clear the selection if Ctrl is not pressed
SelectedCells.Clear();
}
foreach (var item in Items)
{
var cellInfo = new DataGridCellInfo(item, column);
if (!SelectedCells.Contains(cellInfo))
{
SelectedCells.Add(cellInfo);
}
}
}
#endregion
#region Delete Contents in Selected Cells
private static void OnCanExecuteDeleteInternal(object sender, CanExecuteRoutedEventArgs args)
{
((CustomDataGrid)sender).OnCanExecuteDelete(sender, args);
}
private static void OnExecutedDeleteInternal(object sender, ExecutedRoutedEventArgs args)
{
((CustomDataGrid)sender).OnExecutedDelete(sender, args);
}
protected virtual void OnCanExecuteDelete(object sender, CanExecuteRoutedEventArgs args)
{
//Check for External Handlers
if (CanExecuteDeleteEvent != null)
{
CanExecuteDeleteEvent(sender, args);
if (args.Handled)
{
return;
}
}
//Default Delete Event Handler for our CustomDatagrid Class
args.CanExecute = true;
args.Handled = true;
}
protected virtual void OnExecutedDelete(object sender, ExecutedRoutedEventArgs args)
{
var customDataGrid = sender as CustomDataGrid;
if (customDataGrid != null)
{
customDataGrid.DeleteSelectedCells();
}
args.Handled = true;
}
private void DeleteSelectedCells()
{
Mouse.OverrideCursor = Cursors.Wait;
if (SelectedCells.Count == 0)
{
return;
}
//Step 1: To get the selected rows for cases where we need to remove the whole row from the datagrid
List selectedRows = new List();
foreach (DataGridCellInfo cellInfo in SelectedCells)
{
if (cellInfo.IsValid && cellInfo.Item != null && !selectedRows.Contains(cellInfo.Item))
{
selectedRows.Add(cellInfo.Item);
}
}
//Step 2: For each selected row, check if all cells in the row is selected and delete the cell value in a selected cell
foreach (var selectedRow in selectedRows)
{
List AllCellsInARowSelected = new List();
foreach (DataGridColumn column in Columns)
{
bool CurrCellSelected = false;
var cellInfo = new DataGridCellInfo(selectedRow, column);
if (column is DataGridTextColumn && cellInfo.IsValid)
{
var propertyName = column.SortMemberPath; //Assuming SortMemberPath is set to the property name in the column binding
if (SelectedCells.Contains(cellInfo))
{
CurrCellSelected = true;
var dataItem = cellInfo.Item;
var cellValue = dataItem.GetType().GetProperty(propertyName)?.GetValue(dataItem, null);//Get the actual value of the property
var property = cellInfo.Item.GetType().GetProperty(propertyName);
if(property != null)
{
var propertyType = property.PropertyType;
// Type string is a non-generic reference type, but does not need to differenciate nullable since even though it is not nullable, default value is null
// Nullable and non - nullable distinctions are primarily applicable to value types, not reference types
// In this case, IsClass is used instead of (propertyType == typeof(string))
// Nullable value types are represented by the generic type Nullable
// As a result, isNullable is false when the property is a non-nullable value type
//Step 2-1: If the cell contains not null or empty value, delete(null or set default val) the data in the cells
if (!string.IsNullOrWhiteSpace(cellValue?.ToString()))
{
bool isNullable = propertyType.IsClass || (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable));
var emptyValue = isNullable ? null : Activator.CreateInstance(propertyType);
property?.SetValue(cellInfo.Item, emptyValue);
}
}
}
}
//step 2-2: To Chek if all cells in a row are contained in selectedCells
AllCellsInARowSelected.Add(CurrCellSelected);
}
// Step 3: If all cells in the row are contained in selectedCells, except the first column where row select button resides in, delete the row
if (AllCellsInARowSelected.Count(value => !value) == 1)
{
if (ItemsSource is IList itemList)
{
itemList.Remove(selectedRow);
}
}
}
//Step 4: If selectedRow contains not null or Empty values OR selected cells are from different rows, delete the data in the cells
//foreach (DataGridCellInfo cellInfo in SelectedCells)
//{
// if (cellInfo.IsValid && cellInfo.Item != null && cellInfo.Column != null)
// {
// DataGridColumn column = null;
// column = cellInfo.Column as DataGridColumn;
// column?.OnPastingCellClipboardContent(cellInfo.Item, "");
// }
//}
SelectedCells.Clear();
Mouse.OverrideCursor = null;
}
#endregion
// ******************************************************************
#region Clipboard Paste
// ******************************************************************
private static void OnCanExecutePasteInternal(object target, CanExecuteRoutedEventArgs args)
{
((CustomDataGrid)target).OnCanExecutePaste(target, args);
}
// ******************************************************************
///
/// This virtual method is called when ApplicationCommands.Paste command query its state.
///
///
///
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);
}
// ******************************************************************
///
/// This virtual method is called when ApplicationCommands.Paste command is executed.
///
///
///
protected virtual void OnExecutedPaste(object target, ExecutedRoutedEventArgs args)
{
this.CanUserResizeColumns = false;
this.AutoGenerateColumns = false;
if (ExecutePasteEvent != null)
{
ExecutePasteEvent(target, args);
if (args.Handled)
{
return;
}
}
Mouse.OverrideCursor = Cursors.Wait;
// parse the clipboard data [row][column]
List clipboardData = ClipboardHelper2.ParseClipboardData();
bool hasAddedNewRow = false;
int minRowIndex = Items.IndexOf(CurrentItem);
int maxRowIndex = Items.Count - 1;
int startIndexOfDisplayCol = (SelectionUnit != DataGridSelectionUnit.FullRow) ? CurrentColumn.DisplayIndex : 0;
//int startIndexOfDisplayCol = CurrentColumn.DisplayIndex;
int clipboardRowIndex = 0;
for (int i = minRowIndex; i
Подробнее здесь: [url]https://stackoverflow.com/questions/79361990/custom-datagrid-copy-paste-wpf[/url]
Мы реализовали решение для копирования и вставки данных в Datagrid. Там, где мы получили решение, оно очень хорошо работает для того, что мы пытаемся сделать. Однако мы искали способы ускорить фактическую вставку данных: для небольших объемов данных вставка происходит довольно быстро, но как только набор данных начинает становиться немного больше, мы видим, что скорость замедляется. Итак, я просто ищу способ ускорить функцию вставки, или я знаю, что представления списков иногда в некоторых отношениях работают быстрее, просто не могу придумать, как использовать этот код для разработки нового представления списка копирования/вставки. Если у вас есть предложения, дайте мне знать, спасибо [code]public class CustomDataGrid : DataGrid { public event ExecutedRoutedEventHandler ExecutePasteEvent; public event CanExecuteRoutedEventHandler CanExecutePasteEvent; public event CanExecuteRoutedEventHandler CanExecuteDeleteEvent; private bool ctrlPressed = false;
static CustomDataGrid() {
CommandManager.RegisterClassCommandBinding( typeof(CustomDataGrid), new CommandBinding(ApplicationCommands.Paste, new ExecutedRoutedEventHandler(OnExecutedPasteInternal), new CanExecuteRoutedEventHandler(OnCanExecutePasteInternal)));
CommandManager.RegisterClassCommandBinding( typeof(CustomDataGrid), new CommandBinding(ApplicationCommands.Delete, new ExecutedRoutedEventHandler(OnExecutedDeleteInternal), new CanExecuteRoutedEventHandler(OnCanExecuteDeleteInternal)));
}
public CustomDataGrid() { PreviewKeyDown += OnPreviewKeyDown; PreviewKeyUp += OnPreviewKeyUp;
}
#region Selecting all cells in the clicked column protected override void OnSorting(DataGridSortingEventArgs eventArgs) { SelectColumnCells(eventArgs.Column); //base.OnSorting(eventArgs); eventArgs.Handled = true;
//Step 1: To get the selected rows for cases where we need to remove the whole row from the datagrid List selectedRows = new List();
foreach (DataGridCellInfo cellInfo in SelectedCells) { if (cellInfo.IsValid && cellInfo.Item != null && !selectedRows.Contains(cellInfo.Item)) { selectedRows.Add(cellInfo.Item); } }
//Step 2: For each selected row, check if all cells in the row is selected and delete the cell value in a selected cell foreach (var selectedRow in selectedRows) { List AllCellsInARowSelected = new List();
foreach (DataGridColumn column in Columns) { bool CurrCellSelected = false; var cellInfo = new DataGridCellInfo(selectedRow, column);
if (column is DataGridTextColumn && cellInfo.IsValid) { var propertyName = column.SortMemberPath; //Assuming SortMemberPath is set to the property name in the column binding
if (SelectedCells.Contains(cellInfo)) { CurrCellSelected = true;
var dataItem = cellInfo.Item; var cellValue = dataItem.GetType().GetProperty(propertyName)?.GetValue(dataItem, null);//Get the actual value of the property var property = cellInfo.Item.GetType().GetProperty(propertyName); if(property != null) { var propertyType = property.PropertyType;
// Type string is a non-generic reference type, but does not need to differenciate nullable since even though it is not nullable, default value is null // Nullable and non - nullable distinctions are primarily applicable to value types, not reference types // In this case, IsClass is used instead of (propertyType == typeof(string)) // Nullable value types are represented by the generic type Nullable // As a result, isNullable is false when the property is a non-nullable value type
//Step 2-1: If the cell contains not null or empty value, delete(null or set default val) the data in the cells if (!string.IsNullOrWhiteSpace(cellValue?.ToString())) { bool isNullable = propertyType.IsClass || (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable)); var emptyValue = isNullable ? null : Activator.CreateInstance(propertyType); property?.SetValue(cellInfo.Item, emptyValue); } } } } //step 2-2: To Chek if all cells in a row are contained in selectedCells AllCellsInARowSelected.Add(CurrCellSelected); } // Step 3: If all cells in the row are contained in selectedCells, except the first column where row select button resides in, delete the row if (AllCellsInARowSelected.Count(value => !value) == 1) { if (ItemsSource is IList itemList) { itemList.Remove(selectedRow); } } }
//Step 4: If selectedRow contains not null or Empty values OR selected cells are from different rows, delete the data in the cells //foreach (DataGridCellInfo cellInfo in SelectedCells) //{ // if (cellInfo.IsValid && cellInfo.Item != null && cellInfo.Column != null) // { // DataGridColumn column = null; // column = cellInfo.Column as DataGridColumn; // column?.OnPastingCellClipboardContent(cellInfo.Item, ""); // } //} SelectedCells.Clear(); Mouse.OverrideCursor = null; }
// ****************************************************************** /// /// This virtual method is called when ApplicationCommands.Paste command query its state. /// ///
// ****************************************************************** /// /// This virtual method is called when ApplicationCommands.Paste command is executed. /// /// /// protected virtual void OnExecutedPaste(object target, ExecutedRoutedEventArgs args) { this.CanUserResizeColumns = false; this.AutoGenerateColumns = false; if (ExecutePasteEvent != null) { ExecutePasteEvent(target, args); if (args.Handled) { return; } } Mouse.OverrideCursor = Cursors.Wait; // parse the clipboard data [row][column] List clipboardData = ClipboardHelper2.ParseClipboardData();
bool hasAddedNewRow = false;
int minRowIndex = Items.IndexOf(CurrentItem); int maxRowIndex = Items.Count - 1; int startIndexOfDisplayCol = (SelectionUnit != DataGridSelectionUnit.FullRow) ? CurrentColumn.DisplayIndex : 0; //int startIndexOfDisplayCol = CurrentColumn.DisplayIndex; int clipboardRowIndex = 0; for (int i = minRowIndex; i
Мы реализовали решение для копирования и вставки данных в Datagrid. Там, где мы получили решение, оно очень хорошо работает для того, что мы пытаемся сделать. Однако мы искали способы ускорить фактическую вставку данных: для небольших объемов данных...
Мы реализовали решение для копирования и вставки данных в Datagrid. Там, где мы получили решение, оно очень хорошо работает для того, что мы пытаемся сделать. Однако мы искали способы ускорить фактическую вставку данных: для небольших объемов данных...
Я внедряю пользовательский буферизатор, который не разрешает операцию копирования / вставки из других приложений. Текст, скопированный в приложении, может быть вставлен только в приложение. Пожалуйста, помогите мне с пользовательским веб...
У меня есть следующий код, где я копирую, а затем вставлю некоторые вещи, как следующие в текстовой области. У меня есть настройка таким образом, потому что когда я вставляю следующие три строки, курсор остается сразу после последней строки hij123 и...