none
RichTextBlock 内の TextElement をクリックしてページ遷移させる際、パラメーターを渡すには RRS feed

  • 質問

  • 静的なリッチテキスト内の Hyperlink 要素から Click イベントで単純なページ遷移の処理を行うのは容易ですが、動的に生成されるリッチテキスト内の TextElement に対するクリックでページを遷移させると同時に、移動先のページへ値渡しを行いたい場合、どのような方法が考えられるでしょうか。動作のイメージとしては、Twitter for Windows で URL をクリックした際に、アプリケーション内でそのページを開くような形です。

    まず Hyperlink.NavigateUri に値を格納し、それを参照させることを考えました。

    var link = new Hyperlink();
    link.Inlines.Add(inline);
    link.NavigateUri = uri;
    link.Click += link_Click; // クリック イベントの発生と同時にブラウザーが起動する

    link_Click メソッドで記述した値渡し付きのページ遷移はうまく動いています。しかし、NavigateUri プロパティが設定されている場合、Hyperlink をクリックした際に、クリック イベントと同時にブラウザーが起動されてしまいます。

    次に、Hyperlink 要素にプロパティを追加しようと考えましたが、Hyperlink クラスは sealed クラスであるため、これを直接継承するクラスは作成できません。そこで、Hyperlink の親クラスである Span クラスから派生クラスを作ろうと考えました。

    public sealed class InternalLink : Span
    {
        public Uri Url { get; set; }
    
        public event EventHandler Click; // インスタンス側で Click イベントを付与するコードでは問題が検出されないものの、ビルドした段階でエラーを指摘される
    }

    var link = new InternalLink();
    link.Inlines.Add(inline);
    link.Url = uri;
    link.Click += link_Click;

    しかしこのコードの場合、一見すると InternalLink のインスタンスに Click イベントを付与することはできているように見えるものの、ビルドした段階で EventHandler Click の定義にて「イベント 'MyApp.page.InternalLink.Click' は使用されませんでした」のエラーが指摘されます。実際、テスト実行してみても link はクリックできずに通常のテキストと同様とみなされているようでした。

    Hyperlink.Click からブラウザーが起動されるのをキャンセルするか、Span の派生クラスに Click イベントを付与できればいいのですが、他の方法でも解決できるのならご教授願いたいです。

    • 編集済み asato2001 2014年9月16日 3:31
    2014年9月16日 3:29

回答

  • 動的に生成できるかは確認していませんが、InlineUIContainer はどうでしょう?

    <Paragraph>
      abc
      <InlineUIContainer>
        <TextBlock Tapped="TextBlock_Tapped">他のページへ遷移</TextBlock>
      </InlineUIContainer>
      def
    </Paragraph>
    


    biac [ http://bluewatersoft.cocolog-nifty.com/ ]

    • 回答としてマーク asato2001 2014年9月17日 3:14
    2014年9月16日 3:57

すべての返信

  • 動的に生成できるかは確認していませんが、InlineUIContainer はどうでしょう?

    <Paragraph>
      abc
      <InlineUIContainer>
        <TextBlock Tapped="TextBlock_Tapped">他のページへ遷移</TextBlock>
      </InlineUIContainer>
      def
    </Paragraph>
    


    biac [ http://bluewatersoft.cocolog-nifty.com/ ]

    • 回答としてマーク asato2001 2014年9月17日 3:14
    2014年9月16日 3:57
  • TextBlock に Tapped イベントが用意されていたのですね。InlineUIContainer で Control を埋め込むことは検討していましたが、HyperlinkButton を整形して使おうかと考えていました。HyperlinkButton をテキストの中に調和するよう整形を加える労力を考えると、TextBlock を埋め込むほうが現実的な方法ですね。

    var container = new InlineUIContainer();
    
    var link = new TextBlock
    {
        Text = linkText,
        Tag = url,
    };
    link.Tapped += link_Tapped;
    
    container.Child = link;
    paragraph.Inlines.Add(container);

    しかし別の問題があったようで、InlineUIContainer 内の要素から Tapped イベントが発行される際、イベントが二回発生しているようです。InlineUIContainer 外の TextBlock に設定した Tapped イベントや、InlineUIContainer 内の要素から発生する Click イベントでは同様の現象は発生しませんでした。

    これは link_Tapped メソッドで TappedRoutedEventArgs の Handled プロパティを true に設定することで解決できました。

    void link_Tapped(object sender, TappedRoutedEventArgs e)
    {
        e.Handled = true;
        var url = (sender as TextBlock).Tag;
        Frame.Navigate(typeof(ItemPage), url);
    }
    • 編集済み asato2001 2014年9月17日 3:39
    2014年9月17日 3:13