none
FlowDocumentReader内にあるTableのセルにボタンを表示させ、そのボタンのContentを検索させる方法 RRS feed

  • 質問

  • ご存じの方がいれば考え方を教えていただきたいです。

    XAMLにFlowDocumentReaderを利用しております。

    FlowDocumentReaderには、標準で検索機能がついており、

    内部のTableのParagraphで囲んだテキストを検索させることができます。

    ここで、テキストの代わりに、ボタンを表示させ、そのボタンのContextを検索させたいと考えております。

    (FlowDocument内で、別のページにジャンプさせるボタンを設置させたいと考えました。)

    おそらくカスタマイズが必要ではないかと考え、FlowDocumentReaderのテンプレートを確認すると、

    検索ボタンには、以下のようなテンプレートがセットしてあり、ApplicationCommands.Findというコマンドがバインドしてありました。

    ApplicationCommandsというのはビルトインコマンドとの説明があったのですが、

    このコマンドをカスタマイズすることは可能でしょうか?

    もしくは、やりたいことを実現するためには、コマンドを自作する必要があるのでしょうか?

    やりたいこと

    XAML(メイン画面)

       <Grid>
    
            <FlowDocumentReader IsPrintEnabled="False" IsTwoPageViewEnabled="False" Template="{StaticResource FlowDocumentReaderControlTemplate1}">
                <FlowDocument FontFamily="メイリオ" ColumnWidth="1000">
                    <Table>
                        <Table.Columns>
                            <TableColumn Width="60"/>
                            <TableColumn Width="120*"/>
                            <TableColumn Width="*"/>
                        </Table.Columns>
    
                        <TableRowGroup>
    
                            <TableRow>
                                <TableCell ColumnSpan="4" TextAlignment="Left">
                                    <Paragraph FontSize="16pt">History</Paragraph>
                                </TableCell>
                            </TableRow>
    
                            <TableRow Background="LightGoldenrodYellow">
                                <TableCell ColumnSpan="4">
                                    <Paragraph Margin="2,0,0,0">2013/10/28</Paragraph>
                                </TableCell>
                            </TableRow>
    
                            <TableRow>
                                <TableCell>
                                    <Paragraph FontSize="13" Margin="5,0,0,0">13:52</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph FontSize="13" Foreground="Blue">
                                        A
                                        <Button Content="A" Margin="-5,0,0,0" Cursor="Hand"/>
                                    </Paragraph>
                                </TableCell>
                                <TableCell>
                                </TableCell>
                            </TableRow>
                            <TableRow Background="lightgray">
                                <TableCell>
                                    <Paragraph FontSize="13" Margin="5,0,0,0">13:54</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph FontSize="13">B</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph></Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph FontSize="13" Margin="5,0,0,0">13:56</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph FontSize="13">C</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph></Paragraph>
                                </TableCell>
                            </TableRow>
                        </TableRowGroup>
                    </Table>
                </FlowDocument>
            </FlowDocumentReader>
        </Grid>

    XAMLの(FlowDocumentのテンプレートから検索ボタンのところを抜粋)

                        <StackPanel Grid.Column="0" Orientation="Horizontal" Uid="StackPanel_5">
                            <ToggleButton x:Name="FindButton" Command="ApplicationCommands.Find" Focusable="False" Margin="3,0" ToolTip="検索" Uid="ToggleButton_1">
                                <ToggleButton.Style>
                                    <Style TargetType="{x:Type ToggleButton}">
                                        <Style.BasedOn>
                                            <Style TargetType="{x:Type ButtonBase}">
                                                <Setter Property="Focusable" Value="False"/>
                                                <Setter Property="Opacity" Value="0.5"/>
                                                <Setter Property="Cursor" Value="Hand"/>
                                                <Setter Property="Background" Value="Transparent"/>
                                                <Setter Property="Padding" Value="3,1"/>
                                                <Setter Property="BorderBrush" Value="{x:Null}"/>
                                                <Setter Property="BorderThickness" Value="0"/>
                                                <Setter Property="MinWidth" Value="0"/>
                                                <Setter Property="MinHeight" Value="0"/>
                                                <Setter Property="Template">
                                                    <Setter.Value>
                                                        <ControlTemplate TargetType="{x:Type ButtonBase}">
                                                            <Border Background="{TemplateBinding Background}" Uid="Border_39">
                                                                <ContentPresenter x:Name="Content" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" RenderTransformOrigin="0.5,0.5" Uid="ContentPresenter_2"/>
                                                            </Border>
                                                            <ControlTemplate.Triggers>
                                                                <Trigger Property="IsMouseOver" Value="True">
                                                                    <Setter Property="RenderTransform" TargetName="Content">
                                                                        <Setter.Value>
                                                                            <ScaleTransform ScaleY="1.1" ScaleX="1.1"/>
                                                                        </Setter.Value>
                                                                    </Setter>
                                                                </Trigger>
                                                                <Trigger Property="IsPressed" Value="True">
                                                                    <Setter Property="RenderTransform" TargetName="Content">
                                                                        <Setter.Value>
                                                                            <ScaleTransform ScaleY="0.9" ScaleX="0.9"/>
                                                                        </Setter.Value>
                                                                    </Setter>
                                                                </Trigger>
                                                            </ControlTemplate.Triggers>
                                                        </ControlTemplate>
                                                    </Setter.Value>
                                                </Setter>
                                                <Style.Triggers>
                                                    <Trigger Property="IsEnabled" Value="False">
                                                        <Setter Property="Opacity" Value="0.3"/>
                                                    </Trigger>
                                                    <Trigger Property="IsMouseOver" Value="True">
                                                        <Setter Property="Opacity" Value="1"/>
                                                    </Trigger>
                                                </Style.Triggers>
                                            </Style>
                                        </Style.BasedOn>
                                        <Style.Triggers>
                                            <Trigger Property="IsEnabled" Value="False">
                                                <Setter Property="Visibility" Value="Collapsed"/>
                                            </Trigger>
                                            <Trigger Property="IsChecked" Value="True">
                                                <Setter Property="Opacity" Value="1"/>
                                            </Trigger>
                                        </Style.Triggers>
                                    </Style>
                                </ToggleButton.Style>
                                <Path Stroke="{TemplateBinding Foreground}" Uid="Path_23" VerticalAlignment="Center">
                                    <Path.Data>
                                        <GeometryGroup>
                                            <RectangleGeometry RadiusY="1" RadiusX="1" Rect="0.5,0.5,19,19"/>
                                            <EllipseGeometry Center="12,8" RadiusY="5" RadiusX="5"/>
                                            <EllipseGeometry Center="12,8" RadiusY="4" RadiusX="4"/>
                                            <LineGeometry EndPoint="9,10" StartPoint="2.5,16.5"/>
                                            <LineGeometry EndPoint="9.5,10.5" StartPoint="3,17"/>
                                            <LineGeometry EndPoint="10,11" StartPoint="3.5,17.5"/>
                                        </GeometryGroup>
                                    </Path.Data>
                                </Path>
                            </ToggleButton>
                            <Border x:Name="PART_FindToolBarHost" HorizontalAlignment="Left" Uid="Border_64" Visibility="Collapsed" VerticalAlignment="Center"/>
                        </StackPanel>







    • 編集済み sasagaki 2013年12月3日 0:38
    2013年12月3日 0:29

回答

  • こんな。

    FlowDocumentReaderにおいてApplicationCommands.Findは検索文字入力のTextBoxの表示非表示を切り替えてるだけで、検索機能を実装しているわけではないようだ。
    Findコマンドを捕まえてもあまり意味がなく、直接検索処理すれば済むことです。

    <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="200" Width="525">
        <Grid>
            <Frame NavigationUIVisibility="Hidden"
                    PreviewKeyDown="Frame_PreviewKeyDown"
                    Navigating="Frame_Navigating">
                <UIElement.CommandBindings>
                    <CommandBinding Command="NavigationCommands.Search" 
                                    CanExecute="SearchCommandBinding_CanExecute" 
                                    Executed="SearchCommandBinding_Executed"/>
                </UIElement.CommandBindings>
                <Frame.Content>
                    <FlowDocumentReader x:Name="fdreader" IsPrintEnabled="False" IsTwoPageViewEnabled="False">
    
                        <FlowDocument FontFamily="メイリオ" ColumnWidth="1000">
                            <Table>
                                <Table.Columns>
                                    <TableColumn Width="60"/><TableColumn Width="120*"/><TableColumn Width="*"/>
                                </Table.Columns>
    
                                <TableRowGroup>
    
                                    <TableRow>
                                        <TableCell ColumnSpan="4" TextAlignment="Left"><Paragraph FontSize="16pt">History</Paragraph></TableCell>
                                    </TableRow>
    
                                    <TableRow Background="LightGoldenrodYellow">
                                        <TableCell ColumnSpan="4"><Paragraph Margin="2,0,0,0">2013/10/28</Paragraph></TableCell>
                                    </TableRow>
    
                                    <TableRow>
                                        <TableCell><Paragraph FontSize="13" Margin="5,0,0,0">13:52</Paragraph></TableCell>
    
                                        <TableCell>
                                            <Paragraph FontSize="13" Foreground="Blue">
                                                A
    
                                                <Hyperlink NavigateUri="#T1400" Background="LightBlue"  >
                                                    A1
                                                </Hyperlink>
    
                                                <Hyperlink NavigateUri="Page1.xaml" Background="LightPink" >A</Hyperlink>
    
                                                <Button Content="A2" Command="{Binding Commands[Test]}" />
                                            </Paragraph>
    
                                        </TableCell>
    
                                        <TableCell></TableCell>
                                    </TableRow>
    
                                    <TableRow ><TableCell/></TableRow>
                                    <TableRow ><TableCell/></TableRow>
                                    <TableRow ><TableCell/></TableRow>
                                    <TableRow ><TableCell/></TableRow>
                                    <TableRow ><TableCell/></TableRow>
                                    <TableRow ><TableCell/></TableRow>
    
                                    <TableRow Background="lightgray">
                                        <TableCell><Paragraph FontSize="13" Margin="5,0,0,0">13:54</Paragraph></TableCell>
                                        <TableCell><Paragraph FontSize="13">B</Paragraph></TableCell>
                                        <TableCell><Paragraph/></TableCell>
                                    </TableRow>
    
                                    <TableRow>
                                        <TableCell><Paragraph FontSize="13" Margin="5,0,0,0" Name="T1356">13:56</Paragraph></TableCell>
                                        <TableCell><Paragraph FontSize="13">C</Paragraph></TableCell>
                                        <TableCell><Paragraph/></TableCell>
                                    </TableRow>
    
                                    <TableRow><TableCell><Paragraph FontSize="13" Margin="5,0,0,0">13:58</Paragraph></TableCell></TableRow>
                                    <TableRow>
                                        <TableCell><Paragraph FontSize="13" Margin="5,0,0,0" Name="T1400">14:00</Paragraph></TableCell>
                                        <TableCell> <Paragraph>A</Paragraph></TableCell></TableRow>
                                    <TableRow><TableCell><Paragraph FontSize="13" Margin="5,0,0,0">14:02</Paragraph> </TableCell> </TableRow>
                                    <TableRow><TableCell><Paragraph FontSize="13" Margin="5,0,0,0">14:04</Paragraph></TableCell></TableRow>
                                    <TableRow><TableCell><Paragraph FontSize="13" Margin="5,0,0,0">14:06</Paragraph></TableCell></TableRow>
                                </TableRowGroup>
                            </Table>
                        </FlowDocument>
                    </FlowDocumentReader>
                </Frame.Content>
            </Frame>
        </Grid>
    </Window>
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Navigation;
    
    namespace WpfApplication1
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void Frame_PreviewKeyDown(object sender, KeyEventArgs e)
            {
                if ((OriginalSourceIsFindTextBox(e) && e.Key == Key.Enter) || e.Key == Key.F3)
                {
                    //Searchコマンドを発行する必要はないけど試しに使ってみる
                    NavigationCommands.Search.Execute(string.Empty, Keyboard.FocusedElement);
                    //Search();
                    e.Handled = true;
                }
            }
    
            private TextBox findTextBox = null; //検索文字入力用のTextBox
            private FrameworkElement findToolBarHost = null;//検索文字入力用のコントロール
    
            /// <summary>キー入力されたTextBoxが検索文字入力用か調べる</summary>
            /// <param name="e"></param>
            /// <returns></returns>
            private bool OriginalSourceIsFindTextBox(KeyEventArgs e)
            {
                TextBox txb = e.OriginalSource as TextBox;
    
                if (txb != null && txb.Name == "FindTextBox")
                {
                    if (txb == findTextBox)
                    {
                        return true;
                    }
    
                    DependencyObject d = txb;
                    do
                    {
                        FrameworkElement fe = d as FrameworkElement;
                        if (fe != null && fe.Name == "PART_FindToolBarHost")
                        {
                            findToolBarHost = fe;
                            findTextBox = txb;
                            return true;
                        }
                        d = VisualTreeHelper.GetParent(d);
    
                    } while (d != null);
    
                }
                return false;
            }
    
            private void SearchCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
            {
                //Searchコマンドが実行可能か
                e.CanExecute = true;
                e.Handled = true;
            }
    
            private void SearchCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
            {
                //Searchコマンドを実行する
                Search();
            }
    
            private void Search()
            {
                if (findTextBox != null && findTextBox.IsVisible && !string.IsNullOrEmpty(findTextBox.Text))
                {
                    //検索用TextBox内でのEnterかF3での検索の場合に検索文字が入力済みなら自前で検索する
                    Search(this.fdreader, findTextBox.Text);
    
                }
            }
    
            /// <summary>FlowDocumentReaderでInlineUIContainerの文字列も検索してみる</summary>
            /// <param name="fdreader"></param>
            /// <param name="find"></param>
            private static void Search(FlowDocumentReader fdreader, string find)
            {
                if (string.IsNullOrEmpty(find))
                {
                    return;
                }
                FlowDocument doc = fdreader.Document;
                TextPointer pointer = fdreader.Selection.End;
                while (pointer != null)
                {
                    var context = pointer.GetPointerContext(LogicalDirection.Forward);
                    switch (context)
                    {
                    case TextPointerContext.EmbeddedElement:
                        var container = pointer.Parent as InlineUIContainer;
                        if (container != null)
                        {
                            var cont = container.Child as ContentControl;//ContentControlのみを検索対象にする
                            string s = cont.Content as string;
                            if (s != null && s.Contains(find))
                            {
                                fdreader.Selection.Select(pointer, pointer.GetNextContextPosition(LogicalDirection.Forward));
    
                                //cont.Focus();//検索続行できなくなるよ
                                return;
                            }
                        }
                        pointer = pointer.GetNextContextPosition(LogicalDirection.Forward);
                        break;
                    case TextPointerContext.Text:
                        string text = pointer.GetTextInRun(LogicalDirection.Forward);
                        int index = text.IndexOf(find);
                        if (index >= 0)
                        {
                            var endpointer = pointer.GetPositionAtOffset(find.Length);
                            //fdreader.Focus();
                            fdreader.Selection.Select(pointer, endpointer);
                            if (pointer.Paragraph != null)
                            {
                                //見つかった文字列のParagraphの位置を表示できるなら表示
                                pointer.Paragraph.BringIntoView();
                            }
                            pointer = endpointer;
    
                            return;
                        }
                        else
                        {
                            pointer = pointer.GetPositionAtOffset(text.Length);
                        }
                        break;
                    default:
                        pointer = pointer.GetNextContextPosition(LogicalDirection.Forward);
                        break;
                    }
                }
                MessageBox.Show(Application.Current.MainWindow, "最後まで検索しました");
            }
    
            /// <summary>おまけ。HyperLinkで移動する時</summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void Frame_Navigating(object sender, NavigatingCancelEventArgs e)
            {
                if (e.Uri != null && !e.Uri.OriginalString.StartsWith("#"))
                {//別ページに移動するときにはFlowDocumentの中身を変えてみる
                    //同一Document内の移動(#)は何もしないでFrameに任せる
                    e.Cancel = true;
                    FlowDocument doc = new FlowDocument();
    
                    Section sec = new Section();
                    Paragraph p = new Paragraph();
                    p.Inlines.Add(new Run("404 Page not found"));
                    sec.Blocks.Add(p);
                    doc.Blocks.Add(sec);
    
                    fdreader.Document = doc;
                }
            }
        }
    }

    試しにNavigationCommands.Searchを使う実装をしていますが、FlowDocumentReaderがF3キーを使ってしまっていて CommandBindingsがうまく動かないので、PreviewKeyDownでSearchコマンドを発行するという変なやり方になってます。

    #別ページへのジャンプならHyperLinkの方が素直な実装な気がする。


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク sasagaki 2013年12月5日 5:39
    2013年12月4日 13:33

すべての返信

  • こんな。

    FlowDocumentReaderにおいてApplicationCommands.Findは検索文字入力のTextBoxの表示非表示を切り替えてるだけで、検索機能を実装しているわけではないようだ。
    Findコマンドを捕まえてもあまり意味がなく、直接検索処理すれば済むことです。

    <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="200" Width="525">
        <Grid>
            <Frame NavigationUIVisibility="Hidden"
                    PreviewKeyDown="Frame_PreviewKeyDown"
                    Navigating="Frame_Navigating">
                <UIElement.CommandBindings>
                    <CommandBinding Command="NavigationCommands.Search" 
                                    CanExecute="SearchCommandBinding_CanExecute" 
                                    Executed="SearchCommandBinding_Executed"/>
                </UIElement.CommandBindings>
                <Frame.Content>
                    <FlowDocumentReader x:Name="fdreader" IsPrintEnabled="False" IsTwoPageViewEnabled="False">
    
                        <FlowDocument FontFamily="メイリオ" ColumnWidth="1000">
                            <Table>
                                <Table.Columns>
                                    <TableColumn Width="60"/><TableColumn Width="120*"/><TableColumn Width="*"/>
                                </Table.Columns>
    
                                <TableRowGroup>
    
                                    <TableRow>
                                        <TableCell ColumnSpan="4" TextAlignment="Left"><Paragraph FontSize="16pt">History</Paragraph></TableCell>
                                    </TableRow>
    
                                    <TableRow Background="LightGoldenrodYellow">
                                        <TableCell ColumnSpan="4"><Paragraph Margin="2,0,0,0">2013/10/28</Paragraph></TableCell>
                                    </TableRow>
    
                                    <TableRow>
                                        <TableCell><Paragraph FontSize="13" Margin="5,0,0,0">13:52</Paragraph></TableCell>
    
                                        <TableCell>
                                            <Paragraph FontSize="13" Foreground="Blue">
                                                A
    
                                                <Hyperlink NavigateUri="#T1400" Background="LightBlue"  >
                                                    A1
                                                </Hyperlink>
    
                                                <Hyperlink NavigateUri="Page1.xaml" Background="LightPink" >A</Hyperlink>
    
                                                <Button Content="A2" Command="{Binding Commands[Test]}" />
                                            </Paragraph>
    
                                        </TableCell>
    
                                        <TableCell></TableCell>
                                    </TableRow>
    
                                    <TableRow ><TableCell/></TableRow>
                                    <TableRow ><TableCell/></TableRow>
                                    <TableRow ><TableCell/></TableRow>
                                    <TableRow ><TableCell/></TableRow>
                                    <TableRow ><TableCell/></TableRow>
                                    <TableRow ><TableCell/></TableRow>
    
                                    <TableRow Background="lightgray">
                                        <TableCell><Paragraph FontSize="13" Margin="5,0,0,0">13:54</Paragraph></TableCell>
                                        <TableCell><Paragraph FontSize="13">B</Paragraph></TableCell>
                                        <TableCell><Paragraph/></TableCell>
                                    </TableRow>
    
                                    <TableRow>
                                        <TableCell><Paragraph FontSize="13" Margin="5,0,0,0" Name="T1356">13:56</Paragraph></TableCell>
                                        <TableCell><Paragraph FontSize="13">C</Paragraph></TableCell>
                                        <TableCell><Paragraph/></TableCell>
                                    </TableRow>
    
                                    <TableRow><TableCell><Paragraph FontSize="13" Margin="5,0,0,0">13:58</Paragraph></TableCell></TableRow>
                                    <TableRow>
                                        <TableCell><Paragraph FontSize="13" Margin="5,0,0,0" Name="T1400">14:00</Paragraph></TableCell>
                                        <TableCell> <Paragraph>A</Paragraph></TableCell></TableRow>
                                    <TableRow><TableCell><Paragraph FontSize="13" Margin="5,0,0,0">14:02</Paragraph> </TableCell> </TableRow>
                                    <TableRow><TableCell><Paragraph FontSize="13" Margin="5,0,0,0">14:04</Paragraph></TableCell></TableRow>
                                    <TableRow><TableCell><Paragraph FontSize="13" Margin="5,0,0,0">14:06</Paragraph></TableCell></TableRow>
                                </TableRowGroup>
                            </Table>
                        </FlowDocument>
                    </FlowDocumentReader>
                </Frame.Content>
            </Frame>
        </Grid>
    </Window>
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Navigation;
    
    namespace WpfApplication1
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void Frame_PreviewKeyDown(object sender, KeyEventArgs e)
            {
                if ((OriginalSourceIsFindTextBox(e) && e.Key == Key.Enter) || e.Key == Key.F3)
                {
                    //Searchコマンドを発行する必要はないけど試しに使ってみる
                    NavigationCommands.Search.Execute(string.Empty, Keyboard.FocusedElement);
                    //Search();
                    e.Handled = true;
                }
            }
    
            private TextBox findTextBox = null; //検索文字入力用のTextBox
            private FrameworkElement findToolBarHost = null;//検索文字入力用のコントロール
    
            /// <summary>キー入力されたTextBoxが検索文字入力用か調べる</summary>
            /// <param name="e"></param>
            /// <returns></returns>
            private bool OriginalSourceIsFindTextBox(KeyEventArgs e)
            {
                TextBox txb = e.OriginalSource as TextBox;
    
                if (txb != null && txb.Name == "FindTextBox")
                {
                    if (txb == findTextBox)
                    {
                        return true;
                    }
    
                    DependencyObject d = txb;
                    do
                    {
                        FrameworkElement fe = d as FrameworkElement;
                        if (fe != null && fe.Name == "PART_FindToolBarHost")
                        {
                            findToolBarHost = fe;
                            findTextBox = txb;
                            return true;
                        }
                        d = VisualTreeHelper.GetParent(d);
    
                    } while (d != null);
    
                }
                return false;
            }
    
            private void SearchCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
            {
                //Searchコマンドが実行可能か
                e.CanExecute = true;
                e.Handled = true;
            }
    
            private void SearchCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
            {
                //Searchコマンドを実行する
                Search();
            }
    
            private void Search()
            {
                if (findTextBox != null && findTextBox.IsVisible && !string.IsNullOrEmpty(findTextBox.Text))
                {
                    //検索用TextBox内でのEnterかF3での検索の場合に検索文字が入力済みなら自前で検索する
                    Search(this.fdreader, findTextBox.Text);
    
                }
            }
    
            /// <summary>FlowDocumentReaderでInlineUIContainerの文字列も検索してみる</summary>
            /// <param name="fdreader"></param>
            /// <param name="find"></param>
            private static void Search(FlowDocumentReader fdreader, string find)
            {
                if (string.IsNullOrEmpty(find))
                {
                    return;
                }
                FlowDocument doc = fdreader.Document;
                TextPointer pointer = fdreader.Selection.End;
                while (pointer != null)
                {
                    var context = pointer.GetPointerContext(LogicalDirection.Forward);
                    switch (context)
                    {
                    case TextPointerContext.EmbeddedElement:
                        var container = pointer.Parent as InlineUIContainer;
                        if (container != null)
                        {
                            var cont = container.Child as ContentControl;//ContentControlのみを検索対象にする
                            string s = cont.Content as string;
                            if (s != null && s.Contains(find))
                            {
                                fdreader.Selection.Select(pointer, pointer.GetNextContextPosition(LogicalDirection.Forward));
    
                                //cont.Focus();//検索続行できなくなるよ
                                return;
                            }
                        }
                        pointer = pointer.GetNextContextPosition(LogicalDirection.Forward);
                        break;
                    case TextPointerContext.Text:
                        string text = pointer.GetTextInRun(LogicalDirection.Forward);
                        int index = text.IndexOf(find);
                        if (index >= 0)
                        {
                            var endpointer = pointer.GetPositionAtOffset(find.Length);
                            //fdreader.Focus();
                            fdreader.Selection.Select(pointer, endpointer);
                            if (pointer.Paragraph != null)
                            {
                                //見つかった文字列のParagraphの位置を表示できるなら表示
                                pointer.Paragraph.BringIntoView();
                            }
                            pointer = endpointer;
    
                            return;
                        }
                        else
                        {
                            pointer = pointer.GetPositionAtOffset(text.Length);
                        }
                        break;
                    default:
                        pointer = pointer.GetNextContextPosition(LogicalDirection.Forward);
                        break;
                    }
                }
                MessageBox.Show(Application.Current.MainWindow, "最後まで検索しました");
            }
    
            /// <summary>おまけ。HyperLinkで移動する時</summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void Frame_Navigating(object sender, NavigatingCancelEventArgs e)
            {
                if (e.Uri != null && !e.Uri.OriginalString.StartsWith("#"))
                {//別ページに移動するときにはFlowDocumentの中身を変えてみる
                    //同一Document内の移動(#)は何もしないでFrameに任せる
                    e.Cancel = true;
                    FlowDocument doc = new FlowDocument();
    
                    Section sec = new Section();
                    Paragraph p = new Paragraph();
                    p.Inlines.Add(new Run("404 Page not found"));
                    sec.Blocks.Add(p);
                    doc.Blocks.Add(sec);
    
                    fdreader.Document = doc;
                }
            }
        }
    }

    試しにNavigationCommands.Searchを使う実装をしていますが、FlowDocumentReaderがF3キーを使ってしまっていて CommandBindingsがうまく動かないので、PreviewKeyDownでSearchコマンドを発行するという変なやり方になってます。

    #別ページへのジャンプならHyperLinkの方が素直な実装な気がする。


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク sasagaki 2013年12月5日 5:39
    2013年12月4日 13:33
  • gekka様

     お忙しいところ、ご回答ありがとうございました。

     Application.Findは、ビルトインコマンドであり、このコマンドのカスタマイズを考えるのではなく、

     自分で実装した方が早いとのこと、ありがとうございました。

     また、ButtonよりもHyperLinkを使った方がよいとのアドバイスや

     エラーメッセージの実装、pointer,NavigationCommandsの使い方など、

     知らなかったことが多くあり、勉強になりました。

     本当にありがとうございました。


    • 編集済み sasagaki 2013年12月5日 5:40
    2013年12月5日 5:38