问题
I have a flowdocument like this:
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;
and I need an event to trigger on mouse click on a textblock:
<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;
}
The event handler for Run is called and works properly (Changing inline in flowdocument) , but that for TextBlock isn't.
What am I doing wrong? Thanks
回答1:
Quote from MSDN:
Important
RichTextBox has built-in handling for the bubbling MouseUp and MouseDown events. Consequently, custom event handlers that listen for MouseUp or MouseDown events from a RichTextBox will never be called. If you need to respond to these events, listen for the tunneling PreviewMouseUp and PreviewMouseDown events instead, or register the handlers with the HandledEventsToo argument (this latter option is only available through code). Do not mark the event handled unless you deliberately want to disable RichTextBox native handling of these events, and be aware that this has notable effects on the control's UI.
So you need to look for alternatives. I can suggest a few.
First, you can set an event handler PreviewMouseDown
for all RichTextBox
:
<RichTextBox PreviewMouseDown="TextBlock_Click" ... />
Second, use the BlockUIContainer
and put the text in the content button. For example:
<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>
Third, you can set the event handler for the Paragraph
like that:
var para = new Paragraph();
para.Inlines.Add(textBlock1);
para.MouseLeftButtonDown += new MouseButtonEventHandler(TextBlock_Click);
Edit
Quote from Adam Nathan's book WPF 4 Unleashed
:
Whereas TextBox exposes simple integer properties such as CaretIndex, SelectionStart, and SelectionEnd, RichTextBox exposes a CaretPosition property of type TextPointer and a Selection property of type TextSelection. In addition, RichTextBox’s content is stored in a Document property of type FlowDocument rather than the simple string Text property. The content can even contain embedded UIElements, and they can be interactive and raise events if RichTextBox’s IsDocumentEnabled property is set to true.
Events began to work, it is necessary to add BlockUIContainer
with IsDocumentEnabled property is set to true
(in RichTextBox
), otherwise, the event will not working altogether.
In general, I do not understand why you need it TextBlock
inside RichTextBox
. Use it the standard features, they pretty much cover, those Run
, Paragraph
, etc. If they do not match, then there is no reason to use RichTextBox
.
See the nice tutorial about RichTextBox
here.
来源:https://stackoverflow.com/questions/17908449/clicking-on-a-textblock-in-wpf-richtextbox