locked
DataGridの特定のセルだけをハイパーリンクにしたい

    質問

  • DataGridの特定のセルだけをハイパーリンクにしたいのですが、技術的に可能でしょうか?

    XAML に DataGridTemplateColumn.CellTemplate や、HyperlinkButton を指定すれば、
    列単位でハイパーリンクに出来ることは分かっていますが、なるべく XAML を使用しないで、
    特定のセルを、コードだけで実現したいと思います。

    こちらのサイトを参考にして、特定のセルの背景色を変えることには成功しました。
    http://shinichiaoyagi.blog25.fc2.com/blog-entry-176.html

    同様にDataGridCell を触ればよいのかなと思いますが、やり方を教えてください。


    2011年10月6日 8:56

回答

  • 失礼、HyperlinkはUIElementを継承していませんね。
    可能ならHyperlinkButtonを使ってみてください。

        var link = new HyperlinkButton()
        {
            NavigateUri = new Uri("http://www.yahoo.co.jp"),
            Content = "http://www.yahoo.co.jp"
        };
    
        dataGridCell.Content = link;
    

    ContentControl クラス (System.Windows.Controls)
    「Content を UIElement に設定した場合、ContentControl には UIElement が表示されます。Content をそれ以外の種類のオブジェクトに設定した場合、そのオブジェクトの文字列表現が ContentControl に表示されます。」(引用)

    2011年10月11日 17:49
  • 解決されていますが、別のアプローチを。表示に関するデータをクラスに保持しておいて、それを参照してXAMLで表示するコントロールのVisibilityを切り替える方法です。

    https://skydrive.live.com/#!/?cid=c0989b857f2f850c&sc=documents&id=C0989B857F2F850C%213033


    かずき Blog:http://d.hatena.ne.jp/okazuki/ VS 2010のデザイナでBlendのBehaviorをサポートするツール公開してます。 http://vsbehaviorsupport.codeplex.com/
    2011年10月12日 2:28

すべての返信

  • 表示されている特定のセルだけをHyperlinkにするだけなら
    VisualTreeHelper で親を見つけてそいつにHyperlinkを追加すれば良いでしょうけど、

    いろいろ条件によってHyperlinkに変えたいとかならCellTemplateの方にHyperlinkを配置しておいて
    Visiblityを変化させることで対応するのが良いんじゃ無いかと思います。
    2011年10月6日 16:12
  • Uchida様、どうもありがとうございます。
    取りあえず、ご紹介いただいた方法の上の方法でいきたいと思います。

    下記のようにソースコードを組んでみました。
    一部、以前のスレッドで紹介したDataGridViewを使用していますが、実体はDataGridとほぼ同じです。

    DataGridViewCell dgv_cell = new DataGridViewCell(0);
    dgv_cell.ColumnIndex = 1;
    dgv_cell.RowIndex = 1;
    FrameworkElement cell = dataGridView1.GetGridCell(dgv_cell);   ----- (1)
    DependencyObject cell_parent = VisualTreeHelper.GetParent(cell);
    Hyperlink MyLink = new Hyperlink();
    MyLink.Inlines.Add("MSDN SITE");
    MyLink.NavigateUri = new Uri("http://www.msdn.com");

    (1)で得られたcellは、DataGridCellです。その親のcell_parentに、Hyperlinkを追加
    したいのですが、cell_parentにAddなどのメソッドがありません。
    どのように追加すればよろしいのでしょうか?


    2011年10月7日 3:21
  • DataGridCellを取れているなら、
    DataGridCell.Content = ハイパーリンク
    

    でOKじゃないですかね。
    (Contentの中を取ってきているのかと思ったので親とか書きました。)
    2011年10月7日 16:29
  • ご指摘のとおり、DataGridCell.Content = ハイパーリンク としてみましたが、
    指定したセルに、ハイパーリンク自体は書かれずに、
    「System.Windows.Documents.Hyperlink」という文字列が表示されてしまいます。
    下にソースコードを貼り付けます。

    private void LoadButton_Click(object sender, RoutedEventArgs e)
    {
      DataGridViewCell dgv_cell = new DataGridViewCell(0);
      dgv_cell.ColumnIndex = 1;
      dgv_cell.RowIndex = 1;
      DataGridCell cell = (DataGridCell)dataGridView1.GetGridCell(dgv_cell);
      Hyperlink MyLink = new Hyperlink();
      MyLink.Inlines.Add("MSDN SITE");
      MyLink.NavigateUri = new Uri("http://www.msdn.com");

      cell.Content = MyLink;
    }

    たとえば、cell.Content = "Kawata";
    とか、試してみたら、普通に「Kawata」という文字列が入りました。

    ソースコードに不具合はありますでしょうか?

    2011年10月11日 1:12
  • 失礼、HyperlinkはUIElementを継承していませんね。
    可能ならHyperlinkButtonを使ってみてください。

        var link = new HyperlinkButton()
        {
            NavigateUri = new Uri("http://www.yahoo.co.jp"),
            Content = "http://www.yahoo.co.jp"
        };
    
        dataGridCell.Content = link;
    

    ContentControl クラス (System.Windows.Controls)
    「Content を UIElement に設定した場合、ContentControl には UIElement が表示されます。Content をそれ以外の種類のオブジェクトに設定した場合、そのオブジェクトの文字列表現が ContentControl に表示されます。」(引用)

    2011年10月11日 17:49
  • ご教示いただいたプログラムで試してみたら、無事にハイパーリンクになりました!!

    どうもありがとうございました。

    2011年10月12日 0:56
  • 解決されていますが、別のアプローチを。表示に関するデータをクラスに保持しておいて、それを参照してXAMLで表示するコントロールのVisibilityを切り替える方法です。

    https://skydrive.live.com/#!/?cid=c0989b857f2f850c&sc=documents&id=C0989B857F2F850C%213033


    かずき Blog:http://d.hatena.ne.jp/okazuki/ VS 2010のデザイナでBlendのBehaviorをサポートするツール公開してます。 http://vsbehaviorsupport.codeplex.com/
    2011年10月12日 2:28
  • かずき様、どうもありがとうございます。
    こちらの方も、ぜひ参考にさせていただきます。

    ところで、余談で申し訳ないのですが、ハイパーリンクで例えば下記のようなURLにしたとします。

    http://localhost:1345/dg3371TestPage.aspx?staff_id=1007&staff_date=2011/10/03

    このURLの文字列から、変数 staff_id=1007, staff_date=2011/10/03 を抜き出すような
    効果的な方法はないでしょうか?
    Perlとかですと、ライブラリが用意されていて、簡単に抜き出すことが出来るのですが。
    リンク先でGETパラメータを読み込むように処理をさせても良いのですが、リンク先で処理を任せるのではなく、リンク先をクリックした時点で、イベントを読み込むようにしておいて、そのときの状態(ここでは2つの変数)に
    応じて、任意のページ遷移を行わせたいと考えております。

    2011年10月12日 7:46
  • 別の問題になってしまうので、別の質問としてフォーラムに立てませんか?

    その方が回答もつきやすいし、同じ問題にぶちあたった人が探しやすくなるので。 


    かずき Blog:http://d.hatena.ne.jp/okazuki/ VS 2010のデザイナでBlendのBehaviorをサポートするツール公開してます。 http://vsbehaviorsupport.codeplex.com/
    2011年10月12日 8:19
  • そうですね。この質問はSilverlightというよりも、文字列の操作の問題ですので、それ以外のフォーラムがいいでしょうね。どこかお勧めのフォーラムはありますでしょうか? 文章を整理して立てたいと思います。

    2011年10月12日 10:28
  • >かずきさん

    こんにちは。
    最初の返信で
    「いろいろ条件によってHyperlinkに変えたいとかならCellTemplateの方にHyperlinkを配置しておいて
    Visiblityを変化させることで対応するのが良いんじゃ無いかと思います。」

    と書いたように、僕も自分でやるならCellTemplateでやりますね。

    質問がCellTemplate NGなのと、独自実装のDataGridだったのでこういう回答しました。

    P.S. IsNiceMiddleというプロパティ名がステキですね
    2011年10月12日 11:30
  • kawata_sotaro さん
    > どこかお勧めのフォーラムはありますでしょうか?

    別質問(新しい質問)にすべきだと思いますが、フォーラムは変更する必要はないと思いました。
    かずきさんも別フォーラムとは書かれていませんし。

    といいつつ、調べたことをこのスレッドで書かせてもらいます。
    (Silverlight は未経験なので、間違ってたらごめんなさい。)

    Silverlight でなければ System.Web.HttpUtility を使って次のようにできますが、Silverlight では対応するものはないようです。

    var uri = new Uri("http://localhost:1345/dg3371TestPage.aspx?staff_id=1007&staff_date=2011/10/03");
    var queryParams = System.Web.HttpUtility.ParseQueryString(uri.Query);
    var staff_date = queryParams["staff_date"];

    "Silverlight ParseQueryString" で検索してみたところ、見つかった下記サイトでは自作されていました。
    (2つ目のリンク先のコメントに書かれている System.Windows.Browser.HtmlPage.Document.QueryString は、自身のページ用かなと思うので、今回は使えないのですよね)
    (追記:1つめのは自作な話ではありませんでした)

    http://stackoverflow.com/questions/563884/silverlight-3-class-library
    http://bloggingabout.net/blogs/stephan/archive/2008/12/01/passing-query-string-parameters-to-a-silverlight-app-hosted-in-html.aspx

    • 編集済み TH01 2011年10月12日 12:20
    2011年10月12日 12:05
  • Uchida様
    > と書いたように、僕も自分でやるならCellTemplateでやりますね。

    そちらの方がシンプルに出来るのなら、検討してみたいと思います。
    ただ、列が動的に生成される、といった場合にも対応できますでしょうか?

    TH01様

    お調べ頂きまして、どうもありがとうございました。
    QueryStringがキーワードですね。自分でも少し調べてみたいと思います。

    2011年10月13日 0:29
  • かずきさんとUchidaさんがご指摘されたように、DataGridCellに直接データを書き込む処理は、やはりデータ数が増えた場合に破綻しました。

    CellTemplateとVisibilityを使用した方法が、下記のサイトに書かれています。
    みなさん、是非参考にして下さい。

    SilverlightのDataGridで特定のセルをハイパーリンクにする方法
    http://code.msdn.microsoft.com/SilverlightDataGrid-8128c92b

    ただ、今回の場合、列が動的に作成される必要があるため、動的XAMLを使用しました。
    動的XAMLだと、若干不具合が発生するようです。(イベントハンドラーを記述すると実行時にエラーになるとか)

    2011年10月27日 3:00