C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: DataGridで任意の行の先頭表示について


(過去ログ 130 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■76818 / inTopicNo.1)  DataGridで任意の行の先頭表示について
  
□投稿者/ ちー (1回)-(2015/08/20(Thu) 13:25:18)

分類:[.NET 全般] 

開発環境
VB.net2008

実装環境
WindowsCE
Framework 1.1

DataGridで、選択した行の背景色をプログラムで変更すると、グリッドの表示が1行目になってしまいます。
選択行は変わっていないので、下矢印を押下すると、選択行の下行が選択された状態で画面に表示されます。
とりあえず、カレントセルを選択行のセルに設定しましたが、今度は選択行が先頭行に来てしまいます。

DataGrid.VertScrollBarプロパティは、Framework 1.1ではWindowsCEをサポートしていないようで使えません。

処理前のグリッドの表示位置を取得し、処理後に反映する方法をご存じの方がいたら、教えて頂けないでしょうか。
よろしくお願い致します。

引用返信 編集キー/
■76819 / inTopicNo.2)  Re[1]: DataGridで任意の行の先頭表示について
□投稿者/ 魔界の仮面弁士 (452回)-(2015/08/20(Thu) 14:39:09)
No76818 (ちー さん) に返信
> VB.net2008
> Framework 1.1
VB2008 は、.NET Framework 1.1 をサポートしていませんし、
.NET Compact Framework に 1.1 は無かったはずでは…? (1.0/2.0/3.5/3.7/3.9)


> DataGrid.VertScrollBarプロパティは、Framework 1.1ではWindowsCEをサポートしていないようで使えません。
 「.NET Framework」
 「.NET Compact Framework」
 「.NET Micro Framework」
などは、それぞれ別のフレームワークですので、
『Framework 1.1ではWindowsCEをサポートしていない』という表現には違和感があります。



> DataGridで、選択した行の背景色をプログラムで変更すると、グリッドの表示が1行目になってしまいます。
具体的には、どのように変更されているのでしょうか。


> 処理前のグリッドの表示位置を取得し、処理後に反映する方法をご存じの方がいたら、教えて頂けないでしょうか。
質問内容とは方向性が異なるかもしれませんが、
現在のセルの背景色を指定するだけなれば
 Private Sub Form1_Load(…
  Me.DataGrid1.SelectionBackColor = Color.DarkRed
 End Sub
だけで十分かと思います。一方、行全体ということであれば、
DataGridTextBoxColumn.Paint メソッドをオーバーライドしてみてください。

 Protected Overrides Sub Paint(ByVal g As Graphics, …
  If grid.IsSelected(rowNum) Then
   '選択行の描画
  Else
   '非選択行の描画
  End If
 End Sub

※Paint メソッドのオーバーライドには、.NET Compact Framework 2.0 Service Pack 1 以降が必要です。
引用返信 編集キー/
■76820 / inTopicNo.3)  Re[2]: DataGridで任意の行の先頭表示について
□投稿者/ ちー (2回)-(2015/08/20(Thu) 16:38:25)
返答をありがとうございます。

環境については、聞いていたものを書いてしまいました。
すみません。

もう少し詳しく説明しますと、ハンディターミナルにて
バーコード入力を伴うシステム開発をしています。

ハンディターミナルのシステムは
WindowsR Embedded Version 7.00
でした。

FrameWorkはよくわかりませんが、
.NET Compact Framework v3.5
になるのでしょうか?(wiki調べ)

開発時では、ターゲットデバイスをWindowsCEにし、
エミュレータで動作確認をしています。


DataGridの背景色の変更は、Paint メソッドをオーバーライドしています。
背景色を変更する部分を抜き出してみました。

既存プログラムを変更しているので、理解は怪しいですが。。。
他に、列幅や右寄せ設定等しています。
このやり方が良くないのでしょうか?

-------------------------------------------------------------------
Public Class DataGridColumnStyles
    Inherits DataGridTextBoxColumn

    Protected BackColorColNm As String = ""

    '//************************************************************
    '//●BackColor プロパティ
    '//************************************************************
    Public Property BackColorColumnName() As String
        Get
            Return BackColorColNm
        End Get
        Set(ByVal value As String)
            BackColorColNm = value
        End Set
    End Property

    '//************************************************************
    '//●Paint オーバライド
    '//************************************************************
    Protected Overloads Overrides Sub Paint( _
        ByVal g As Graphics, _
        ByVal bounds As Rectangle, _
        ByVal [source] As CurrencyManager, _
        ByVal rowNum As Integer, _
        ByVal backBrush As Brush, _
        ByVal foreBrush As Brush, _
        ByVal alignToRight As Boolean _
    )
        '// 背景色変更
        Dim dtView As System.Data.DataRowView = CType(CType([source], CurrencyManager).List(rowNum), System.Data.DataRowView)
        Dim szArgb As String = dtView.Item(BackColorColNm)
        If szArgb <> "" Then
            backBrush = New SolidBrush(Color.FromArgb(CType(szArgb, Integer)))
        End If
        MyBase.Paint(g, bounds, [source], rowNum, backBrush, foreBrush, alignToRight)

    End Sub
End Class

Public Shared Sub SetAlimentRight( _
      ByRef dg As DataGrid _
    , ByRef dt As DataTable _
    , ByRef RightAlimentFlagList As ArrayList _
    , Optional ByVal BackColorColName As String = "" _
)
    If IsNothing(RightAlimentFlagList) Then Exit Sub

    Dim addTableStyle As New DataGridTableStyle

    For i As Integer = 0 To dt.Columns.Count - 1

        Dim addColumnStyles = New DataGridColumnStyles
        With addColumnStyles
            '// 背景色指定列名
            .BackColorColumnName = BackColorColName
        End With
        addTableStyle.GridColumnStyles.Add(addColumnStyles)

    Next
    dg.TableStyles.Clear()
    dg.TableStyles.Add(addTableStyle)
    dg.DataSource = dt '//dg表示

End Sub

Private Sub dg_SetDeleteRow(ByVal selRow As Integer)

    Dim dtGridData As DataTable = CType(dgList.DataSource, DataTable)
    If selRow = -1 Then

        '// ヘッダクリック
        If mbCheckAllSelect Then
            '// 全解除
            For i As Integer = 0 To dtGridData.Rows.Count - 1
                dtGridData.Rows(i).Item("BACKCOLOR") = ""
            Next
        Else
            '// 全選択
            For i As Integer = 0 To dtGridData.Rows.Count - 1
                dtGridData.Rows(i).Item("BACKCOLOR") = Color.Gray.ToArgb
            Next
        End If
        dgList.DataSource = dtGridData
        '// 全選択フラグ
        mbCheckAllSelect = Not mbCheckAllSelect

    Else
        '// データ行クリック
        If dtGridData.Rows(selRow).Item("BACKCOLOR") = "" Then
            dtGridData.Rows(selRow).Item("BACKCOLOR") = Color.Gray.ToArgb
        Else
            dtGridData.Rows(selRow).Item("BACKCOLOR") = ""
        End If
    End If

    Call DataGridAllColumnStyle.SetAlimentRight(dgList, dtGridData, New ArrayList(New Integer() {3}), "BACKCOLOR")
    Call SelectChangeRow(miRowNum)

    If selRow > 0 Then
        dgList.CurrentCell = New DataGridCell(selRow, 1)
    End If
End Sub

引用返信 編集キー/
■76821 / inTopicNo.4)  Re[3]: DataGridで任意の行の先頭表示について
□投稿者/ 魔界の仮面弁士 (453回)-(2015/08/20(Thu) 18:15:08)
No76820 (ちー さん) に返信
> Public Class DataGridColumnStyles
> Inherits DataGridTextBoxColumn
本題とは関係ないですが、クラス名の Styles という名前からは、
スタイル情報を集めたコレクションクラスを連想してしまい、
少々違和感を覚えました。
(実際はコレクションではなく、「列」定義のクラスなわけですよね)


> backBrush = New SolidBrush(Color.FromArgb(CType(szArgb, Integer)))
New したのであれば、MyBase.Paint 後に backBrush.Dispose() を呼び出しましょう。
(Brush は IDisposable です)

ただし、Paint 内で New していない場合(szArgb = "" の時)はその限りではありません。
New していない場合、その場合、backBrush は「Paint メソッドを呼び出した側」で
管理されているものなので、勝手に Dispose() することはできません。



> 背景色を変更する部分を抜き出してみました。
「選択した行の背景色」を変更している、とのことでしたが、
『選択した行』の判定は、どこで行っているのでしょうか。

コードを見る限りでは、「選択した行」というよりは、
「BackColorColNm で指定した列名」に整数値が入っていて、
それを背景色としているようにも見えますが…。



> 他に、列幅や右寄せ設定等しています。
> このやり方が良くないのでしょうか?
それは別の話なので、問題点を切り分けましょう。

> 背景色を変更する部分を抜き出してみました。
そもそも Paint は「描画」のみを担当するものであって、本来であれば、
それだけで選択行が先頭行になったりするようなものではありません。

そして少なくとも、DataGridColumnStyles クラス内には、
その原因となるようなコードは見当たりません。別の箇所に問題があるのでしょう。

Paint をオーバーライドしていない、標準の DataGridTextBoxColumn を使ったときに
『選択行が先頭行に来てしまう』現象が発生するかどうか、確認してみて下さい。
DataGridColumnStyles クラスを使わずとも問題が再現するようであれば、
問題点は描画処理の部分ではなく、編集作業を行っている箇所にあるのだと思います。


> DataGridで、選択した行の背景色をプログラムで変更すると、グリッドの表示が1行目になってしまいます。

念のため、手元の環境で下記のようなコードを書いてみましたが、
Button1 を押してみても、Color.Red にした行が
先頭にくるような現象は確認できませんでした。


Imports System.Data

Public Class Form1
  Private tbl As New DataTable("DataTable1")

  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    tbl.Rows(11)("BackColor") = Color.Red.ToArgb()
  End Sub

  Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
    tbl.Columns.Add("C1")
    tbl.Columns.Add("C2")
    tbl.Columns.Add("BackColor")

    For r As Integer = 1 To 200
      Dim c As Color = Color.FromArgb(r, 128, 172)
      tbl.Rows.Add(r.ToString("000"), StrDup(r, "*"c), c.ToArgb())
    Next
    tbl.AcceptChanges()

    Dim colC1 As New DataGridColumnStyles()
    colC1.MappingName = "C1"
    colC1.BackColorColumnName = "BackColor"
    Dim colC2 As New DataGridColumnStyles()
    colC2.MappingName = "C2"
    colC2.BackColorColumnName = "BackColor"
    Dim colBackColor As New DataGridTextBoxColumn()
    colBackColor.MappingName = "BackColor"
    colBackColor.Width = 80

    Dim style As New DataGridTableStyle()
    style.MappingName = "DataTable1"
    style.GridColumnStyles.Add(colC1)
    style.GridColumnStyles.Add(colC2)
    style.GridColumnStyles.Add(colBackColor)

    DataGrid1.TableStyles.Clear()
    DataGrid1.TableStyles.Add(style)

    DataGrid1.DataSource = tbl
  End Sub
End Class
引用返信 編集キー/
■76826 / inTopicNo.5)  Re[1]: DataGridで任意の行の先頭表示について
□投稿者/ 魔界の仮面弁士 (454回)-(2015/08/21(Fri) 11:36:39)
No76818 (ちー さん) に返信
> DataGrid.VertScrollBarプロパティは、Framework 1.1ではWindowsCEをサポートしていないようで使えません。

実際には .NET Compact Framework v3.5 だったのですよね。
VertScrollBar 相当の動作が必要ならば、こういうことはできます。
内包コントロールを直接取り出しているので、あまり行儀の良いコードでは無いですけれども。

Private WithEvents VScroll As VScrollBar
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As EventArgs) Handles MyBase.Load
  Me.VScroll = Me.DataGrid1.Controls.OfType(Of VScrollBar)().FirstOrDefault()
End Sub
Private Sub VScroll_ValueChanged(ByVal sender As Object, ByVal e As EventArgs) Handles VScroll.ValueChanged
  Me.Label1.Text = CStr(Me.VScroll.Value)
End Sub



> DataGridで、選択した行の背景色をプログラムで変更すると、
ここでいう「選択した行」とは、何のことでしょうか?

 (a)DataGrid で、反転表示されている行
 (b)DataGrid で、行頭に三角マークのついている行
 (c)DataTable の BackColorColumn 列を操作するための DataRow
 (d)それ以外

a だとしたら、DataGrid の Select および IsSelected メソッドです。
b だとしたら、DataGrid1.BindingContext(DataGrid1.DataSource).Position で読み書きできます。
あるいは、CurrentRowIndex / CurrentCell プロパティ で。


a のメソッドは、スクロールを発生させません。
Select メソッドで指定した行が画面外にあっても、そのままです。

b のプロパティは、指定した行が画面外にあった場合、
それが表示される位置までスクロールします。ただし、
現在と同じ値を再セットした場合はスクロールしません。


c の場合、Binding から辿った場合は、DataGrid の現在行が変化して
b と同様にスクロールします。ただし、バインド元の DataTable の
行を直接書き換えるなどした場合は、スクロールには影響しません。


(上記以外の方法で制御しているのなら、その部分のコードを見せて下さい)
引用返信 編集キー/
■76827 / inTopicNo.6)  Re[2]: DataGridで任意の行の先頭表示について
□投稿者/ ちー (3回)-(2015/08/21(Fri) 11:40:36)
2015/08/21(Fri) 11:42:18 編集(投稿者)

御返答ありがとうございます。
大変助かります。

> 本題とは関係ないですが、クラス名の Styles という名前からは、
> スタイル情報を集めたコレクションクラスを連想してしまい、
> 少々違和感を覚えました。
> (実際はコレクションではなく、「列」定義のクラスなわけですよね)
なるほど。気にしていませんでしたが、そうですね。
稼働中システムの既存クラスの為、このクラス名の変更はできませんが、
今後新しいクラスを作る時には、気を付けようと思います。


> New したのであれば、MyBase.Paint 後に backBrush.Dispose() を呼び出しましょう。
> (Brush は IDisposable です)
ご指摘ありがとうございます。
New した時のみ backBrush.Dispose() を呼ぶよう修正しました。


> 「選択した行の背景色」を変更している、とのことでしたが、
> 『選択した行』の判定は、どこで行っているのでしょうか。
グリッドフォーカス時のEnterキー押下時のCurrentRowIndex
または マウスアップイベントでHitTestInfoからクリック行を取得して
dg_SetDeleteRow関数の引数に渡していました。
そこまで書くべきでした。
すみません。


そして、試して頂いた上、ソースまでありがとうございます!
このソースを試した所、確かに表示は変わりません。。。

原因は、SetAlimentRight関数でグリッドを作り直している?

SetAlimentRight関数を行選択時に呼ぶのをやめたら、背景色だけ変わるようになりました。
よくよく考えれば、列の値を変えれば Paint イベントが呼ばれるわけで、
グリッド列の定義も、初期表示時に定義されてるわけで、再定義をする必要はないのでした。

既存ソースの作りがこうだからと思考停止するのでなく、きちんと中身を理解しなければ
いけないと痛感しました。

魔界の仮面弁士さん。
丁寧に教えてくださり、ありがとうございました!


解決済み
引用返信 編集キー/
■76828 / inTopicNo.7)  Re[3]: DataGridで任意の行の先頭表示について
□投稿者/ ちー (4回)-(2015/08/21(Fri) 12:01:23)
2015/08/21(Fri) 12:05:22 編集(投稿者)
色々試している内にレスが!
再度御返答ありがとうございます。

> VertScrollBar 相当の動作が必要ならば、こういうことはできます。
> 内包コントロールを直接取り出しているので、あまり行儀の良いコードでは無いですけれども。
このような方法もあるのですね。
勉強になります。
今回は使わなくてすみましたが、複数グリッドの表示の同期等の案件が出た時には
使わせていただきます。


> ここでいう「選択した行」とは、何のことでしょうか?
「選択した行」と一言で言っても、色々なケースが考えられるんですね(^^;
(c)のケースは考えた事がありませんでした。
一応、選択行取得のソースを乗せておきます。
色々とありがとうございました。

    Private Sub form_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            AddHandler Me.dgList.MouseUp, AddressOf Me.dg_MouseUp
    End Sub

    Private Sub dg_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs)
        Dim hitinfo As DataGrid.HitTestInfo
        hitinfo = (CType(sender, DataGrid).HitTest(e.X, e.Y))
        Dim selRow As Integer = hitinfo.Row.ToString
        Call dg_SetDeleteRow(selRow)
    End Sub

    Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)
            MyBase.OnKeyDown(e)
            If e.KeyCode = Keys.Enter Then
                Call dg_SetDeleteRow(Me.dgList.CurrentRowIndex)
            End If
            Return
    End Sub



解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -