C# 如何在将BlockUIContainer从FlowDocument复制到剪贴板时设置自定义文本?
我有嵌入BlockUIContainers的flow文档。当用户将包含它们的文本复制到剪贴板时,我想用适当的文本替换它们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) { /
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");
}