我在c#中制作简单的工具应用程序,我有一个文本框,我想粘贴一些文本(大约30万行),但这使得应用程序无响应。我等了大约10分钟,没有任何进展。
是否有一些方法可以更流畅地处理大数据集上的粘贴和复制操作?例如,在Windows记事本中粘贴和复制相同数量的数据只需要几秒钟。
我使用
Windows.ApplicationModel.DataTransfer.Clipboard.GetContent()
,在这个应用程序挂起。示例代码Xaml
<Window
x:Class="App2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App2"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="1" Grid.RowSpan="1">
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="0" Grid.RowSpan="1" Margin="5" VerticalScrollBarVisibility="Visible" >
<TextBox VerticalAlignment="Stretch" HorizontalAlignment="Stretch" IsReadOnly="False" Header="Query Result" Text='{x:Bind pasteResult, Mode=TwoWay}' PlaceholderText="Paste results here" TextWrapping="Wrap"/>
</ScrollViewer>
</Grid>
</Window>
cs file
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
namespace App2
{
/// <summary>
/// An empty window that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainWindow : Window
{
public string pasteResult;
public MainWindow()
{
this.InitializeComponent();
}
}
}
正如@Simon Mourier在评论中提到的,性能问题与剪贴板无关,而是与TextBox
控制处理数据量有关。
那么,让我给您提供另一种选择,使用内置虚拟化的ItemsRepeater
。(在我的笔记本电脑里)大约需要。3秒显示来自剪贴板的50万行文本。
MainWindow.xaml
<Window
x:Class="ClipboardTests.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"
mc:Ignorable="d">
<Grid RowDefinitions="Auto,*">
<StackPanel
Grid.Row="0"
Orientation="Horizontal">
<Button
Click="PasteButton_Click"
Content="Paste" />
<Button
Click="ClearButton_Click"
Content="Clear" />
<TextBlock
x:Name="MessageTextBox"
VerticalAlignment="Center" />
</StackPanel>
<ScrollViewer Grid.Row="1">
<ItemsRepeater x:Name="TextItemsRepeaterControl" />
</ScrollViewer>
</Grid>
</Window>
MainWindow.xaml.cs
using Microsoft.UI.Xaml;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Windows.ApplicationModel.DataTransfer;
namespace ClipboardTests;
public sealed partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private static async Task<IEnumerable<string>> GetTextLinesFromClipboard()
{
DataPackageView dataPackageView = Clipboard.GetContent();
if (dataPackageView.Contains(StandardDataFormats.Text) is true)
{
string text = await dataPackageView.GetTextAsync();
string[] lines = text
.ReplaceLineEndings()
.Split(Environment.NewLine, StringSplitOptions.None);
return lines;
}
return Enumerable.Empty<string>();
}
private async void PasteButton_Click(object sender, RoutedEventArgs e)
{
Stopwatch stopwatch = Stopwatch.StartNew();
IEnumerable<string> lines = await GetTextLinesFromClipboard();
this.TextItemsRepeaterControl.ItemsSource = lines;
stopwatch.Stop();
this.MessageTextBox.Text = $"Pasted {this.TextItemsRepeaterControl.ItemsSourceView.Count} items in {stopwatch.Elapsed.TotalSeconds} s.";
}
private void ClearButton_Click(object sender, RoutedEventArgs e)
{
this.TextItemsRepeaterControl.ItemsSource = null;
}
}