DOBON.NET DOBON.NETプログラミング掲示板過去ログ

DataGridのプロパティ変更)お願いします

分類:[.NET]

テーブルのデータをそのまま表示するDataGridの使い方は知っていますが、
データの値によって、■や□を表示させ、なお且つリンクをはりたいと思います。
データの値が1だったら■、0だったら□、表示させ、
パラメタ付きのHyperLinkを作成したいのです。
そういう場合はどのようにすれば良いのでしょうか?
DataGridのプロパティをテキストからHyperLinkに
変更することって可能なのでしょうか?
まだまだ初心者ですが、よろしくお願いします。
■No934に返信(晋作さんの記事)
> テーブルのデータをそのまま表示するDataGridの使い方は知っていますが、
> データの値によって、■や□を表示させ、なお且つリンクをはりたいと思います。
> データの値が1だったら■、0だったら□、表示させ、
> パラメタ付きのHyperLinkを作成したいのです。
> そういう場合はどのようにすれば良いのでしょうか?
> DataGridのプロパティをテキストからHyperLinkに
> 変更することって可能なのでしょうか?
> まだまだ初心者ですが、よろしくお願いします。

□などの文字表示ですが、いろいろ試したけど難しそうです。
DBからデータを持ってくる時に、事前にクエリーを作成しておき
その中で□■に変換し、UNIONクエリーからデータをReadし
DataGridへ表示する方法はどうでしょうか?

クエリー1
SELECT [Key], "□" as myConvert FROM T_TEST WHERE (flag=0);
クエリー2
SELECT [Key], "■" as myConvert FROM T_TEST WHERE (flag<>0);
クエリー3(Union)
SELECT * FROM クエリー1 UNION SELECT * FROM クエリー2
■No934に返信(晋作さんの記事)
> パラメタ付きのHyperLinkを作成したいのです。
> そういう場合はどのようにすれば良いのでしょうか?
> DataGridのプロパティをテキストからHyperLinkに
> 変更することって可能なのでしょうか?

HyperLinkも難しそうですね、ボタンで代用する方法もあるみたいです
http://rustemsoft.com/dgcolumns.htm

または、非常に複雑ですがDataGridColumnStyleを継承し、LinkLabelをもつ
クラスを作成するかですね。 これについては、Paintでの処理が分からず
断念してしまいました。
■No934に返信(晋作さんの記事)
> テーブルのデータをそのまま表示するDataGridの使い方は知っていますが、
> データの値によって、■や□を表示させ、なお且つリンクをはりたいと思います。
> データの値が1だったら■、0だったら□、表示させ、
> パラメタ付きのHyperLinkを作成したいのです。

前にDataGridのすべてのセルにComboBoxを表示したいという方からの投稿があり、結局DataGridTextBoxColumnからの派生クラスのPaintメソッドをオーバーライドし、ControlPaintを使ってComboBoxを描画したとのことでした。

簡単な方法としては、同様に、あたかもHyperLinkのようにPaintメソッドで四角を表示し、セルかクリックされたら、リンクを表示する(?)というのが考えられそうです。
皆さま返答ありがとうございます。
遅くなりすみません。
スキル不足で理解に苦しんでます。再度、お願いします。
すみません質問内容に誤りがありましたので具体的に記載していただきます。

質問1.DataGridのプロパティをテキストからHyperLinkに
  変更することって可能なのでしょうか?
  と書きましたが、変更ではなく、最初からHyperLinkにしたいです。

Dim dt As DataTable
Dim dr As DataRow
Dim myReader As System.Data.SqlClient.SqlDataReader

dt = New DataTable()

'見出し部分
dt.Columns.Add("見出しA", GetType(string))
dt.Columns.Add(New DataColumn("見出しB", GetType(String)))
dt.Columns.Add(New DataColumn("見出しC", GetType(String)))
dt.Columns.Add(New DataColumn("見出しD", GetType(String)))

'myReader:テーブルの定義部分は省略させていただきます
While myReader.Read()

dr = dt.NewRow 'テーブルの明細行作成

dr(0) = myReader.GetInt32(0) '見出しAに表示されるデータのセット
dr(1) = myReader.GetString(3) '見出しBに〃
dr(2) = " " '見出しCに〃
If myReader.GetInt32(5) = 0 Then
dr(3) = "□" 'HyperLinkにし、パラメタも設定し、文字のフォント、色などをここで設定したいのです
Else
dr(3) = "■"
End If

dt.Rows.Add(dr)
End While

With dataGrid1
.Visible = True
.DataSource = New DataView(dt)
.DataBind()
End With

質問2.他のTipsを参考にしたとき
 Dim ts As New DataGridTableStyle()  と記入すると、
「'型'DataGridTableStyle'が定義されていません。」とエラーになります。
 何故でしょうか?

よろしくお願いします。
こんばんは、晋作さん。ピラルクです。

(インデントミスで一度削除しました)

> 質問1.DataGridのプロパティをテキストからHyperLinkに
>  変更することって可能なのでしょうか?
>  と書きましたが、変更ではなく、最初からHyperLinkにしたいです。

おおよそ以下のようになりますが、これだとセルをマウスで1回ついて
編集対象にし、さらに付いてリンクとなります。このあたりはキーボード
での挙動もからんでいるので、仕様としてどうあるべきかをきっちり
まとめる必要があると思われます。

  '--------+---------+---------+---------*---------+---------+---------+----
  Private Sub Form1_Load(ByVal sender As System.Object, _
                         ByVal e As System.EventArgs) Handles MyBase.Load
    'DataTable
    Dim dt As New DataTable()
    dt.Columns.Add("列名A", GetType(String))
    dt.Columns.Add("列名B", GetType(String))

    'DataTableにダミーDataを10行作成
    Dim i As Integer
    Dim dr As DataRow
    While (i < 10)
      dr = dt.NewRow

      dr(0) = "Data_A:" & i
      If i Mod 2 = 0 Then
        dr(1) = "□http://dobon.net/"
      Else
        dr(1) = "■http://dobon.net/card/index.html"
      End If

      dt.Rows.Add(dr)
      i += 1
    End While

    'ColumnStyle 列0 (普通のText列)
    Dim colA As DataGridColumnStyle = New DataGridTextBoxColumn()
    colA.HeaderText = "見出しA"
    colA.MappingName = "列名A"
    colA.Width = 60

    'ColumnStyle 列1 (HyperLink列)
    Dim colB As DataGridColumnStyle = New DataGridLinkLabelColumn()
    colB.HeaderText = "見出しB"
    colB.MappingName = "列名B"
    colB.Width = 180

    'TableStyleにColumnStyleを設定
    Dim ts As New DataGridTableStyle()
    ts.GridColumnStyles.Add(colA)
    ts.GridColumnStyles.Add(colB)

    'DataGridにTableStyleとDataTableを設定
    DataGrid1.TableStyles.Add(ts)
    DataGrid1.DataSource = New DataView(dt)
  End Sub

End Class

'--------+---------+---------+---------*---------+---------+---------+----
'HyperLink列用の特注ColumnStyle
Public Class DataGridLinkLabelColumn
  Inherits DataGridColumnStyle

  'Edit時(編集時)に使いまわしされるLinkLabel
  Private m_linkLabel As New LinkLabel()

  Public Sub New()
    m_linkLabel.Visible = False
    AddHandler m_linkLabel.LinkClicked, AddressOf LinkLabel_LinkClicked
  End Sub

  Private Sub LinkLabel_LinkClicked(ByVal sender As System.Object, _
              ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs)
    Dim url As New Uri(m_linkLabel.Text.Substring(1))
    'TODO:ここにHyperLinkの処理を記述
  End Sub

  Protected Overrides Sub Abort(ByVal rowNum As Integer)
    Invalidate()
  End Sub

  '編集後の値をModelに返すためだが、Linkは編集しないので実装不要
  'しかし、Link済みなどのstatusをModelで保管させるなら、これは役に立つ
  Protected Overrides Function Commit( _
                               ByVal dataSource As CurrencyManager, _
                               ByVal rowNum As Integer) As Boolean
    Return True
  End Function

  'これがないと編集時にControlが表示されないので注意
  Protected Overrides Sub SetDataGridInColumn(ByVal value As DataGrid)
    MyBase.SetDataGridInColumn(value)
    If Not (m_linkLabel.Parent Is Nothing) Then
      m_linkLabel.Parent.Controls.Remove(m_linkLabel)
    End If
    If Not (value Is Nothing) Then
      value.Controls.Add(m_linkLabel)
    End If
  End Sub

  'MustOverrideなPaint Method
  Protected Overloads Overrides Sub Paint(ByVal g As Graphics, _
                                          ByVal bounds As Rectangle, _
                                          ByVal [source] As CurrencyManager, _
                                          ByVal rowNum As Integer)
    Paint(g, bounds, [source], rowNum, False)
  End Sub

  Protected Overloads Overrides Sub Paint(ByVal g As Graphics, _
                                          ByVal bounds As Rectangle, _
                                          ByVal [source] As CurrencyManager, _
                                          ByVal rowNum As Integer, _
                                          ByVal alignToRight As Boolean)

    Dim val As String = CType(GetColumnValueAtRow([source], rowNum), String)
    Dim backColorBrush As New SolidBrush(DataGridTableStyle.BackColor)
    Dim foreColorBrush As Brush
    Dim valFont As Font

    'HyperLinkの有効無効によりフォント・カラーを変える
    If val.StartsWith("□") Then
      valFont = New Font(DataGridTableStyle.DataGrid.Font, FontStyle.Underline)
      foreColorBrush = SystemBrushes.HotTrack
    Else
      valFont = DataGridTableStyle.DataGrid.Font
      foreColorBrush = Brushes.DarkGray
    End If

    'セル描画処理
    g.FillRectangle(backColorBrush, bounds)
    bounds.Offset(2, 2)
    g.DrawString(val, valFont, foreColorBrush, _
                 RectangleF.FromLTRB(bounds.X, bounds.Y, bounds.Right, bounds.Bottom))

    'm_linkLabelに描画をまかしたいが、それは無理みたい。
    'レンダラーは高速でなければならないというDataGridの設計思想かな。
    'これのせいで、セルのカスタマイズに関してはJTableの方がまだ分かり良いと思う。。。
    'm_linkLabelも継承で作っておき、PaintにDispatchさせてGraphicsに描かせる
    'ことをすれば可能かもしれないが、LinkLabel程度なら描画の負担もないので
    'そんなややこしいことに挑戦しなくても問題ないと思われる。
  End Sub

  'MustOverrideなEdit Method
  Protected Overloads Overrides Sub Edit(ByVal [source] As CurrencyManager, _
                                         ByVal rowNum As Integer, _
                                         ByVal bounds As Rectangle, _
                                         ByVal [readOnly] As Boolean, _
                                         ByVal instantText As String, _
                                         ByVal cellIsVisible As Boolean)
    Dim val As String = CType(GetColumnValueAtRow([source], rowNum), String)

    'HyperLink無効時は無視
    If val.StartsWith("□") Then
      m_linkLabel.Visible = cellIsVisible
    Else
      m_linkLabel.Visible = False
    End If

    'HyperLink有効時は編集セルにm_linkLabelを配置
    If m_linkLabel.Visible Then
      m_linkLabel.Bounds = New Rectangle(bounds.X + 2, bounds.Y + 2, _
                                         bounds.Width - 4, bounds.Height - 4)
      m_linkLabel.Text = val
      m_linkLabel.Visible = True
      DataGridTableStyle.DataGrid.Invalidate(bounds)
    End If
  End Sub

  '以下はサイズ関連のMustOverrideなMethod
  Protected Overrides Function GetPreferredSize( _
                               ByVal g As Graphics, _
                               ByVal value As Object) As Size
    Return New Size(100, GetMinimumHeight())
  End Function

  Protected Overrides Function GetPreferredHeight( _
                               ByVal g As Graphics, _
                               ByVal value As Object) As Integer
    Return GetMinimumHeight()
  End Function

  Protected Overrides Function GetMinimumHeight() As Integer
    Return m_linkLabel.PreferredHeight + 5
  End Function

End Class


> 質問2.他のTipsを参考にしたとき
>  Dim ts As New DataGridTableStyle()  と記入すると、
> 「'型'DataGridTableStyle'が定義されていません。」とエラーになります。
>  何故でしょうか?

プロジェクト名を"DataGridTableStyle"にしたとか。
やってみた結果うまくいきません。

> 'ColumnStyle 列0 (普通のText列)
> Dim colA As DataGridColumnStyle = New DataGridTextBoxColumn()
> colA.HeaderText = "見出しA"
> colA.MappingName = "列名A"
> colA.Width = 60

で、「型'DataGridColumnStyle'が定義されていません。」とエラーになります。
何かの設定が不足してるのでしょうか?

>>質問2.他のTipsを参考にしたとき
>> Dim ts As New DataGridTableStyle()  と記入すると、
>>「'型'DataGridTableStyle'が定義されていません。」とエラーになります。
>> 何故でしょうか?
>
> プロジェクト名を"DataGridTableStyle"にしたとか。

プロジェクト名は、"DataGridTableStyle"にしていません。
一体何なのでしょうか?

皆さん度々すみませんが、よろしくお願いします。
■No1029に返信(晋作さんの記事)
> やってみた結果うまくいきません。
>
>> 'ColumnStyle 列0 (普通のText列)
>> Dim colA As DataGridColumnStyle = New DataGridTextBoxColumn()
>> colA.HeaderText = "見出しA"
>> colA.MappingName = "列名A"
>> colA.Width = 60
>
> で、「型'DataGridColumnStyle'が定義されていません。」とエラーになります。
> 何かの設定が不足してるのでしょうか?

自分の環境では、ばっちりうまくいきピラルクさん凄い!っていう感じです。
さておき、とりあえず下記のようにしてうまくいくか試してはどうでしょう。
<名前空間フル指定>
Dim colA As System.Windows.Forms.DataGridColumnStyle =
New System.Windows.Forms.DataGridTextBoxColumn

ちなみに自分の参照設定は
System
System.Data
System.Drawing
System.Windows.Forms
System.Xml
インポートは
Microsoft.VisualBasic
System
System.Collections
System.Data
System.Diagnostics
System.Drawing
System.Windows.Forms
です。
> さておき、とりあえず下記のようにしてうまくいくか試してはどうでしょう。
> <名前空間フル指定>
> Dim colA As System.Windows.Forms.DataGridColumnStyle =
> New System.Windows.Forms.DataGridTextBoxColumn

結果は、「型'System.Windows.Forms.DataGridColumnStyle'が定義されていません。」
になってしまいます。

> ちなみに自分の参照設定は
> System
> System.Data
> System.Drawing
> System.Windows.Forms
> System.Xml

 これは、Inherits 〜 でしょうか?

> インポートは
> Microsoft.VisualBasic
> System
> System.Collections
> System.Data
> System.Diagnostics
> System.Drawing
> System.Windows.Forms
> です。

これは、System.Windows.Forms だけが、
「インポート'System.Windows.Forms'の名前空間または型'Forms'が見つかりません。」
となってしまいます。

根本的に何か不足してるのでしょうか?
■No1040に返信(晋作さんの記事)
Visual studio .net 2003を使っているのであれば、
ソリューションエクスプローラーの「参照設定」の「+」をクリックし
展開された一覧が
> System
> System.Data
> System.Drawing
> System.Windows.Forms
> System.Xml
です。

ソリューションエクスプローラーのプロジェクトを右クリック→
メニュー→プロパティで表示されるプロパティページの共通プロパティの
中に「インポート」があります。
「インポート」をクリックし表示される一覧が
> Microsoft.VisualBasic
> System
> System.Collections
> System.Data
> System.Diagnostics
> System.Drawing
> System.Windows.Forms
です。
インポートは、各ファイルの先頭に
Imports Microsoft.VisualBasicと宣言することもできます。

是非、同一の参照設定とインポートで試してみてください。
エラーの箇所はだいぶ減りました。
でも後、3ケ所あります。
まだ何か足りないのでしょうか?

1.dg_menu.TableStyles.Add(ts)

のdg_menu.TableStyles で以下のエラーです
'TableStyles' は 'System.Web.UI.WebControls.DataGrid' のメンバではありません。

2.Protected Overrides Sub SetDataGridInColumn(ByVal value As DataGrid)

2-1.SetDataGridInColumn で以下のエラーです
sub 'SetDataGridInColumn' はベース class の sub をオーバーライドしないため、'Overrides' として宣言することはできません。

2-2.DataGrid で以下のエラーです
名前空間 'System.Windows.Forms, System.Web.UI.WebControls' または型 'System.Windows.Forms, System.Web.UI.WebControls' からインポートされた 'DataGrid' が不適切です。

また、このような問題に強くなるにはどのような勉強をすればよろしいでしょうか?

よろしくお願いします。

先ず質問なのですが、作成したいのは、Windowsアプリケーションですか?
ASP.NET WEBアプリケーションですか?

Windowsアプリケーションでは、System.Windows.FormsのDataGridを使用し
ASP.NET WEBアプリケーションではれば、System.Web.UI.WebControlsを使用
すると認識しています。
ですので通常のWindowsアプリケーションであれば、参照設定から
「System.Web」を削除し、System.Web.UI.WebControlsをインポートしないよう
にすれば良いと思います。逆の場合は、逆の設定で!
■No1074に返信(fukuさんの記事)
>
> 先ず質問なのですが、作成したいのは、Windowsアプリケーションですか?
> ASP.NET WEBアプリケーションですか?

ASP.NET WEBアプリケーションです

> Windowsアプリケーションでは、System.Windows.FormsのDataGridを使用し
> ASP.NET WEBアプリケーションではれば、System.Web.UI.WebControlsを使用
> すると認識しています。
> ですので通常のWindowsアプリケーションであれば、参照設定から
> 「System.Web」を削除し、System.Web.UI.WebControlsをインポートしないよう
> にすれば良いと思います。逆の場合は、逆の設定で!

「参照設定」で「参照の追加」でSystem.Web.UI.WebControlsがありません
(この記事にはファイル"er001.gif"が添付されていましたが、削除されました。)
すみません訂正です。
確認しました。

参照設定に
MSDASC
System
System.Data
System.Drawing
System.Web
System.Windows.Forms
System.XML

インポートの設定では、
Microsoft.VisualBasic
System
System.Collections
System.Configuration
System.Data
System.Diagnostics
System.Drawing
System.Web
System.Web.UI.WebControls
System.Web.UI.HtmlControls
System.Windows.Forms

としていますが、いまだに以下のままです。

1.DataGrid1.TableStyles.Add(ts)

のDataGrid1.TableStyles で以下のエラーです
'TableStyles' は 'System.Web.UI.WebControls.DataGrid' のメンバではありません。

2.Protected Overrides Sub SetDataGridInColumn(ByVal value As DataGrid)

2-1.SetDataGridInColumn で以下のエラーです
sub 'SetDataGridInColumn' はベース class の sub をオーバーライドしないため、'Overrides' として宣言することはできません。

2-2.DataGrid で以下のエラーです
名前空間 'System.Windows.Forms, System.Web.UI.WebControls' または型 'System.Windows.Forms, System.Web.UI.WebControls' からインポートされた 'DataGrid' が不適切です。

DOBON.NET | プログラミング道 | プログラミング掲示板