windows 获取和设置剪贴板中的大量文本数据

vq8itlhq  于 2023-01-18  发布在  Windows
关注(0)|答案(1)|浏览(113)

我正在用C#制作一个简单的工具应用程序,我有一个文本框,我想粘贴一些文本(大约300k行),但这使得应用程序没有响应。我等了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();
        }

    }
}
x7yiwoj4

x7yiwoj41#

正如@Simon Mourier在评论中提到的,性能问题与剪贴板无关,而是与TextBox控件处理的数据量有关。
所以,让我给予你另一个选择,使用ItemsRepeater,它带有内置的虚拟化。(在我的笔记本电脑)它需要大约3秒来显示50万行的文本从剪贴板。

主窗口.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>

主窗口.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;
    }
}

相关问题