I am using the RichTextColumns control that VS2012 inserts into the Common folder for Windows Store Apps to display text from a RichTextBlock into multiple columns. The text is divided into verses that can be marked up by Paragraphs, Run, and Spans.

I need to be able to determine which Verse (or section of text) the user Tapped on so that the Verse can be marked (change of background color) and the app can load media that is linked to that particular verse.

In our desktop app we were able to inherit from the Run class and insert a VerseIndex property. We then caught the Click event and and used the x,y coordinates to find the Run that was within that bounds. In WinRt the Run class is sealed, so we cannot inherit from it and some of the other calls that we used for positioning are missing as well.

What method can be used (other than text selection, which we need for user highlighting and cut/paste) to determine the tapped verse and react to that data?

Here is an example of the RichTextColumns display I am using.

    <ScrollViewer x:Name="ChapterScrollViewer" Margin="0,0,0,40"
                  Style="{StaticResource HorizontalScrollViewerStyle}" Background="White" >
        <StackPanel Orientation="Horizontal" Margin="0,0,20,20" >
            <common:RichTextColumns x:Name="richTextColumnsChapter" VerticalAlignment="Top">
                <common:RichTextColumns.ColumnTemplate>
                    <DataTemplate>
                        <RichTextBlockOverflow Width="400" Margin="50,0,0,0"/>
                    </DataTemplate>
                </common:RichTextColumns.ColumnTemplate>
                <RichTextBlock x:Name="mainRichTextBlockChapter" Margin="0,0,0,0" 
                               IsTextSelectionEnabled="True" 
                               IsTapEnabled="True"
                               FontWeight="Light" Width="400" Foreground="Black" VerticalAlignment="Top" FontSize="20">
                    <Paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus tempor scelerisque lorem in vehicula. Aliquam tincidunt, lacus ut sagittis tristique, turpis massa volutpat augue, eu rutrum ligula ante a ante Pellentesque porta, mauris quis interdum vehicula, urna sapien ultrices velit, nec venenatis dui odio in augue. Cras posuere, enim a cursus convallis, neque turpis malesuada erat, ut adipiscing neque tortor ac erat</Paragraph>

                </RichTextBlock>
            </common:RichTextColumns>
        </StackPanel>
    </ScrollViewer>
有帮助吗?

解决方案

As happens most often, taking the time to explain your problem sometimes gives you a fresh look at a possible solution. Here's what I figured out. Hopefully this will help others.

Even though the Run class is sealed, the Span class is not. I added my own DocVerse class inherited from Span which contains my VerseIndex property.

In my View I handle the Tapped event on the RichTextColumns control and using GetPosition I can determine the correct Run that was Tapped. I can then search through my DocVerse classes to see which one contains that Run, giving my my Tapped "verse".

There is an issue with the RichTextColumns class related to the GetPositionFromPoint call. The 1st column is represented by the RichTextBlock, while the following overflow columns are RichTextBlockOverflow controls. Here is the Tapped handler that finds the Tapped "verse" and changes the FontWeight.

    private void RichTextColumns_Tapped(object sender, TappedRoutedEventArgs e)
    {
        RichTextColumns control = sender as RichTextColumns;

        Point pTapped = e.GetPosition(e.OriginalSource as UIElement);
        TextPointer tp = null;

        if (e.OriginalSource is RichTextBlock) // tapped in the 1st column
        {
            tp = control.RichTextContent.GetPositionFromPoint(pTapped);
        }
        else if (e.OriginalSource is RichTextBlockOverflow) // tapped in an overflow column
        {
            tp = (e.OriginalSource as RichTextBlockOverflow).GetPositionFromPoint(pTapped);
        }

        if (tp != null)
        {
            // find out which DocVerse (inherits from Span) contains the Run that was tapped
            Run r = tp.Parent as Run;
            foreach (DocVerse v in control.Verses)
            { 
                if (v.Inlines.Contains(r))
                {
                    v.FontWeight = FontWeights.Bold;
                    Debug.WriteLine(v.VerseIndex);
                }
            }
        }
    }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top