Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在将BlockUIContainer从FlowDocument复制到剪贴板时设置自定义文本?_C#_.net_Wpf_Xaml - Fatal编程技术网

C# 如何在将BlockUIContainer从FlowDocument复制到剪贴板时设置自定义文本?

C# 如何在将BlockUIContainer从FlowDocument复制到剪贴板时设置自定义文本?,c#,.net,wpf,xaml,C#,.net,Wpf,Xaml,我有嵌入BlockUIContainers的flow文档。当用户将包含它们的文本复制到剪贴板时,我想用适当的文本替换它们 private void flowDocumentReader1_KeyUp(object sender, KeyEventArgs e) { // Check for CTRL+C if (e.Key == Key.C && Keyboard.Modifiers == ModifierKeys.Control) { /

我有嵌入BlockUIContainers的flow文档。当用户将包含它们的文本复制到剪贴板时,我想用适当的文本替换它们

private void flowDocumentReader1_KeyUp(object sender, KeyEventArgs e)
{
    // Check for CTRL+C
    if (e.Key == Key.C && Keyboard.Modifiers == ModifierKeys.Control)
    {
        // Get clipboard information
        IDataObject clipboardDataObject = Clipboard.GetDataObject();

        // Get list of available formats currently in clipboard
        string[] formatsInClipboard = clipboardDataObject.GetFormats();

        // Choose a format to use
        string desiredFormat = "Text"; // You can select Text, UnicodeText, Rich Text Format, etc.

        // Check for availability of desired format
        if (Array.IndexOf(formatsInClipboard, desiredFormat) >= 0)
        {
            // Get copied text
            string initialClipboardText = Clipboard.GetData(desiredFormat).ToString();

            // Update copied text
            string newClipboardText = InsertNameAndTimestamps(initialClipboardText);

            // Insert updated text to clipboard
            Clipboard.SetData(desiredFormat, newClipboardText);
        }                
    }
}

// Sample text modification, modify however you like
private string InsertNameAndTimestamps(string initialClipboardText)
{
    return "[MODIFIED TEXT]" + initialClipboardText + "[MODIFIED TEXT]";
}
Upadate: 我有以下聊天界面:

带有时间和用户名的标题是用
BlockUIContainer
s完成的(我不知道如何使用FlowDocument元素)。当用户选择一些消息并将其复制到剪贴板时,用户名和时间不会被复制,因为它们是文本块。我想截取copy命令并适当设置聊天文本的格式


我想做一种转换器,它接收到 BlockUIContainer并基于它返回一些文本

要捕获Ctrl+C,请执行以下操作:

KeyUp += (o, e) =>
{
    if (e.Handled == false)
    {
        if (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)
        {
            lastKeyWasCtrl = true;// lastKeyWasCtrl is field
            return;
        }
        if (lastKeyWasCtrl &&
            e.Key == Key.C)
        {// Ctrl+C pressed

        }
    }
};

最后用了肮脏的伎俩。在“我的容器”附近附加了不可见的段落,其中包含要复制的文本:

<BlockUIContainer />
<Paragraph FontSize="0.1" Foreground="{Binding ElementName=document, Path=Background}" Margin="0">
    <Run Text="{Binding actualText}" />
</Paragraph>

以下是一种通用方法,用于处理从FlowDocumentReader复制到剪贴板的内容

基本逻辑是,使用FlowDocumentReader.KeyUp事件截取CTRL+C,获取刚刚复制到剪贴板的数据,对其进行修改,然后将修改后的数据插入剪贴板

private void flowDocumentReader1_KeyUp(object sender, KeyEventArgs e)
{
    // Check for CTRL+C
    if (e.Key == Key.C && Keyboard.Modifiers == ModifierKeys.Control)
    {
        // Get clipboard information
        IDataObject clipboardDataObject = Clipboard.GetDataObject();

        // Get list of available formats currently in clipboard
        string[] formatsInClipboard = clipboardDataObject.GetFormats();

        // Choose a format to use
        string desiredFormat = "Text"; // You can select Text, UnicodeText, Rich Text Format, etc.

        // Check for availability of desired format
        if (Array.IndexOf(formatsInClipboard, desiredFormat) >= 0)
        {
            // Get copied text
            string initialClipboardText = Clipboard.GetData(desiredFormat).ToString();

            // Update copied text
            string newClipboardText = InsertNameAndTimestamps(initialClipboardText);

            // Insert updated text to clipboard
            Clipboard.SetData(desiredFormat, newClipboardText);
        }                
    }
}

// Sample text modification, modify however you like
private string InsertNameAndTimestamps(string initialClipboardText)
{
    return "[MODIFIED TEXT]" + initialClipboardText + "[MODIFIED TEXT]";
}
通过将复制的文本包装在“[MODIFIED text]”中简化了此示例,这样就可以很容易地看到它的工作原理,即复制FlowDocumentReader中的内容,然后将其粘贴到记事本中

它也可以通过使用纯文本来简化,但是如果您想使用富文本格式,您也可以选择

编辑: 如果无法确定要在复制的文本中插入的内容和位置,则必须手动处理FlowDocumentReader.Selection(因为默认复制行为不会将UIElements复制到剪贴板)

假设您的流程文档如下所示:

<FlowDocumentReader xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="flowDocumentReader1" KeyUp="flowDocumentReader1_KeyUp">
    <FlowDocument>
        <BlockUIContainer>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <TextBlock>qwe</TextBlock>
                <TextBlock Grid.Column="1" TextAlignment="Right">00:15:37</TextBlock>
            </Grid>
        </BlockUIContainer>

        <Paragraph>Hi</Paragraph>

        <BlockUIContainer>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <TextBlock></TextBlock>
                <TextBlock Grid.Column="1" TextAlignment="Right">00:15:48</TextBlock>
            </Grid>
        </BlockUIContainer>

        <Paragraph>How are you?</Paragraph>

    </FlowDocument>
</FlowDocumentReader>
private void flowDocumentReader1_KeyUp(object sender, KeyEventArgs e)
{
    // Check for CTRL+C
    if (e.Key == Key.C && Keyboard.Modifiers == ModifierKeys.Control)
    {
        StringBuilder stringBuilder = new StringBuilder();

        // Prevent duplicate processing
        BlockUIContainer lastBlockUIContainer = null;

        // Get start of selection
        TextPointer currentPointer = flowDocumentReader1.Selection.Start;

        // Process selected text
        while (currentPointer != null && currentPointer.GetOffsetToPosition(flowDocumentReader1.Selection.End) > 0)
        {
            // Check for BlockUIContainer
            BlockUIContainer blockUIContainer = currentPointer.GetAdjacentElement(LogicalDirection.Backward) as BlockUIContainer;
            if (blockUIContainer != null && blockUIContainer != lastBlockUIContainer)
            {
                // Get text from Grid
                Grid grid = blockUIContainer.Child as Grid;
                if (grid != null)
                {
                    string replacementText = String.Format("{0}\t{1}",
                        (grid.Children[0] as TextBlock).Text,
                        (grid.Children[1] as TextBlock).Text
                        );
                    stringBuilder.AppendLine(replacementText);
                }

                // GetAdjacentElement can return the container from multiple TextPointers, so only process once
                lastBlockUIContainer = blockUIContainer;
            }
            else
            {
                // Get text at current position
                string text = currentPointer.GetTextInRun(LogicalDirection.Forward);
                if (!String.IsNullOrEmpty(text))
                {
                    stringBuilder.AppendLine(text);
                }
            }

            // Move to next TextPointer
            currentPointer = currentPointer.GetNextContextPosition(LogicalDirection.Forward);
        }

        // Insert updated text to clipboard
        string newClipboardText = stringBuilder.ToString();
        Clipboard.SetData("Text", newClipboardText);
    }
}

快乐编码

这种方法非常有用,哈洛,但将键挂起以检测Ctrl+C不会检测上下文菜单右键单击->复制事件,但这样做(而且Ctrl+C也会):


类用于将其他对象(即按钮、列表框等)放置在流内容中,因此它实际上取决于您希望从BlockUIContainer中提取的确切文本。我想制作某种转换器,以接收对BlockUIContainer的引用并基于它返回一些文本。唯一的问题是,如何知道BlockUIContainer中UIElements的顺序?你试过用桌子吗?我知道,因为这个模板是我自己做的。事实上,我将使用它的DataContext对象来提取所有需要的数据。嘿,问题是当用户复制文本时,如何使该函数应用于BlockUIContainers?键控处理程序很糟糕,它不仅接受
Ctrl,C
但也包括在
C
之前按下
Ctrl
的任何输入字符串,因为该字段从未重置为false。是,忘了重置其他文件。方法不错,但有一个问题:没有对我的BlockUIContainers的引用,我不知道要插入到哪里和插入什么。一直以来,我以为你这样做是为了在文本周围获得花哨的边框等。是的,在我的解决方案中,我将不可见的小文本放在实际UI容器附近。所以,若用户选择带有标题的整个消息,他也会选择表示标题内容的不可见文本。也有可能用户想要选择没有标题的文本,但选择了不可见的文本,但几率很低,因为字体大小非常小。这是一个非常聪明的方法。我已经想了一段时间了,但我从来没有想过。在我看来,重写ctrl+c有点麻烦。
public YourWindowConstructor()
{
    InitializeComponent();

    DataObject.AddCopyingHandler(flowDocumentReader1, CustomCopyCommand);
}

private void CustomCopyCommand(object sender, DataObjectEventArgs e)
{
    e.CancelCommand(); //disable the default copy behavior that executes after this function returns

    // custom clipboard code here ...

    Clipboard.SetText("new text");
}