在WPF富文本框中点击TextBlock

4
我有一个像这样的FlowDocument:
var mcFlowDoc = new FlowDocument();
var para = new Paragraph();
para.Inlines.Add(textBlock1);
para.Inlines.Add(textBlock2);
para.Inlines.Add(textBlock3);
mcFlowDoc.Blocks.Add(para);
richTextBox1.Document = mcFlowDoc;

我需要一个事件在鼠标点击文本块时触发:

    <RichTextBox Margin="10,10,230,12" Name="richTextBox1" FontFamily="Simplified Arabic" FontSize="16" IsReadOnly="True" IsReadOnlyCaretVisible="False" ForceCursor="False" FlowDirection="RightToLeft" VerticalScrollBarVisibility="Auto">
        <RichTextBox.Resources>
            <Style TargetType="Run">
                <EventSetter Event="MouseLeftButtonDown" Handler="Run_Click" />
            </Style>
            <Style TargetType="TextBlock">
                <EventSetter Event="MouseLeftButtonDown" Handler="TextBlock_Click" />
            </Style>
        </RichTextBox.Resources>
    </RichTextBox>

void TextBlock_Click(object sender, MouseButtonEventArgs e)
        {
            TextBlock tb = sender as TextBlock;
        }

Run的事件处理程序已被调用并正常工作(更改FlowDocument中的行内元素),但TextBlock的事件处理程序不起作用。

我做错了什么吗? 谢谢。


你将FlowDocument分配给richTextBox。你确定richTextBox1也有带有TextBlocks的FlowDocument吗? - LPL
是的,这就是我使用的:textBlock1 = new TextBlock(run1)); - Jerry
我是说你可能有两个RichTextBoxes。一个名为richTextBox,带有FlowDocument,另一个在XAML中声明为richTextBox1,没有内容但具有事件处理。 - LPL
抱歉,两个都是richTextBox1。我刚刚编辑了问题。 - Jerry
1个回答

5
引用自MSDN

重要提示

RichTextBox内置了处理冒泡MouseUp和MouseDown事件的方法。因此,监听来自RichTextBox的MouseUp或MouseDown事件的自定义事件处理程序将永远不会被调用。如果您需要响应这些事件,请改为侦听隧道式PreviewMouseUp和PreviewMouseDown事件,或使用HandledEventsToo参数注册处理程序(此后一种选项仅适用于代码)。除非您有意禁用RichTextBox对这些事件的本机处理,否则不要标记事件已处理,且请注意,这将显著影响控件的用户界面。

因此,您需要寻找替代方案。我可以提供几个建议。

首先,您可以为所有的RichTextBox设置一个PreviewMouseDown事件处理程序:

<RichTextBox PreviewMouseDown="TextBlock_Click" ... />

其次,使用BlockUIContainer将文本放置在内容按钮中。例如:

<Paragraph FontSize="18">Flow Example</Paragraph>

<BlockUIContainer>
  <Button x:Name="MyButton" ClickMode="Release" Click="Button_Click">
    <TextBlock Margin="4" TextWrapping="Wrap">
      Some text
    </TextBlock>
  </Button>
</BlockUIContainer>

第三步,您可以像这样为段落设置事件处理程序:

var para = new Paragraph();
para.Inlines.Add(textBlock1);

para.MouseLeftButtonDown += new MouseButtonEventHandler(TextBlock_Click);

编辑

来自Adam Nathan的书WPF 4 Unleashed的引用:

虽然TextBox公开了像CaretIndex,SelectionStart和SelectionEnd这样的简单整数属性,但RichTextBox公开了一个类型为TextPointer的CaretPosition属性和一个类型为TextSelection的Selection属性。此外,RichTextBox的内容存储在类型为FlowDocument而不是简单字符串Text属性的Document属性中。内容甚至可以包含嵌入式UIElements,如果RichTextBox的IsDocumentEnabled属性设置为true,则它们可以是交互式的并引发事件。

为使事件起作用,必须将BlockUIContainer添加到 RichTextBox 中,并将IsDocumentEnabled 属性设置为 true,否则该事件将完全无效。

总的来说,我不明白为什么你需要在RichTextBox内使用TextBlock。使用标准功能即可,它们已经涵盖了大部分的RunParagraph等,如果它们不匹配,则没有理由使用RichTextBox

请参见有关RichTextBox的良好教程此处


谢谢,但我忘了提到Run的类似代码可以正常工作(我刚刚编辑了问题)。为什么TextBlock也不能正常工作呢? - Jerry
@Jerry:我认为答案在引用中:“自定义事件处理程序监听来自RichTextBox的MouseUp或MouseDown事件”。显然,这适用于“RichTextBox”中的内容。我尝试了各种鼠标事件来处理“TextBlock”,但没有成功。 - Anatoliy Nikolaev
是的,但在RichTextBox中运行也可以。你试过了吗?它们被不同对待吗? - Jerry
请问您能否给我更多细节信息?我是一个 WPF 的新手。 - Jerry
谢谢。我最初使用 TextBlock 是因为我有一个 Run,我想将它提升到行级别以上,而且只能在 TextBlock 中找到 BaselineOffset 属性。 - Jerry
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接