none
DataGridViewに配列をバインドするには? RRS feed

  • 質問

  • DataGridViewコントロールを操作する101の方法

    http://japan.internet.com/developer/20070522/26.html

     

    上記Webページの「配列をバインドする」「カスタムオブジェクトをバインドする」を参考に

    DataGridViewに配列をバインドしました。

     これを素に、プログラムを作ってみました。

    Public Class Form1
        Private students(65535) As CStudent
        Private count As Integer
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            DataGridView1.DataSource = students
            count = 0
        End Sub
        Private Sub Button調査_Click(sender As Object, e As EventArgs) Handles Button調査.Click
    
             students(count) = New CStudent(TextBox調査.Text, strword, intspon)
           DataGridView1.DataSource = students
            count += 1
    
        End Sub
    End Class
    
    Public Class CStudent
        Private _キーワード As String
        Private _複合ワード As String
        Private _ライバル数 As String
    
        Public Sub New(ByVal キーワード As String, ByVal 複合ワード As String, ByVal ライバル数 As String)
            _複合ワード = 複合ワード
            _キーワード = キーワード
            _ライバル数 = ライバル数
        End Sub
    
        Public Property キーワード() As String
            Get
                Return _キーワード
            End Get
    
            Set(ByVal value As String)
                _キーワード = value
            End Set
        End Property
    
        Public Property 複合ワード() As String
            Get
                Return _複合ワード
            End Get
    
            Set(ByVal value As String)
                _複合ワード = value
            End Set
        End Property
    
        Public Property ライバル数() As String
            Get
                Return _ライバル数
            End Get
    
            Set(ByVal value As String)
                _ライバル数 = value
            End Set
        End Property
    End Class
    
    

    これを動かした結果 → 動画

    マウスで行をクリックしない限り値が対応していません。

    バインドさせるには、どうしたら良いですか。

    ご教示下さい。

    よろしくお願いします。

    2013年5月15日 23:56

回答

  • > 上記Webページの「配列をバインドする」「カスタムオブジェクトをバインドする」を参考に

    その資料では、最初に2件のCStudent をつくり、それらを含んだstudents配列を渡していますが、提示頂いたコードでは、最初に65536個分の要素を持ったstudents配列を作ってはいるものの、それらの各要素はNothingのままで、CStudentを一件も含んでいない状態からはじめているため、微妙に異なるバインドになっていますね。

    > マウスで行をクリックしない限り値が対応していません。

    スクロールしたり、フォームを画面外までドラッグすることでも表示されませんか?

    > バインドさせるには、どうしたら良いですか。

    単純な対応としては、値を更新したタイミングで「DataGridView1.InvalidateRow(count)」を実行するという手法があります。
    これは「バインド元のデータを更新したので、count行を再描画して欲しい」と依頼するためのコードです。

    ただ、今の実装だと「値が変更されたことを通知する機能」が用意されていませんし、件数の増減時にも対応できませんので、もしもデータの編集なども考えてられるのなら、配列ではなくDataSetで管理したほうが、データバインドするには便利ですよ。

    • 回答としてマーク taokato 2013年5月16日 5:42
    2013年5月16日 1:38
  • DataGridViewはDataSourceへオブジェクトがセットされた段階で、そのオブジェクトの描写を行います。ただし、既に設定されているオブジェクトと同じオブジェクトをセットしても描写を行いません。今回掲載されているコードでは、Loadイベントでstudentsをセットしてしまっているため、Button調査_Clickイベントハンドラでstudentsをセットしても描写が行われないわけです。
    よって、この状況を回避するために、DataSourceに一度students以外のものをセットすれば良いことになります。この場合は以下のようにNothingが適切でしょう。

    DataGridView1.DataSource = Nothing
    DataGridView1.DataSource = students

    違う方法としては、DataGridView1に再描写をさせれば良いわけですから、
    DataGridView1.Refresh()や、
    DataGridView1.Invalidate()
    を実行すれば良いでしょう。

    ちなみに配列はバインドには向きません。なぜなら、配列に変更があったことをバインド先に教えることができないからです。教えることができれば、DataGridView側で、Refresh()やInvalidate()などで再描写する必要が無くなります。
    例えば、IBindingListを実装しているBindingListなどを配列の代わりに使用すれば良いでしょう。



    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/


    2013年5月16日 1:38
    モデレータ

すべての返信

  • > 上記Webページの「配列をバインドする」「カスタムオブジェクトをバインドする」を参考に

    その資料では、最初に2件のCStudent をつくり、それらを含んだstudents配列を渡していますが、提示頂いたコードでは、最初に65536個分の要素を持ったstudents配列を作ってはいるものの、それらの各要素はNothingのままで、CStudentを一件も含んでいない状態からはじめているため、微妙に異なるバインドになっていますね。

    > マウスで行をクリックしない限り値が対応していません。

    スクロールしたり、フォームを画面外までドラッグすることでも表示されませんか?

    > バインドさせるには、どうしたら良いですか。

    単純な対応としては、値を更新したタイミングで「DataGridView1.InvalidateRow(count)」を実行するという手法があります。
    これは「バインド元のデータを更新したので、count行を再描画して欲しい」と依頼するためのコードです。

    ただ、今の実装だと「値が変更されたことを通知する機能」が用意されていませんし、件数の増減時にも対応できませんので、もしもデータの編集なども考えてられるのなら、配列ではなくDataSetで管理したほうが、データバインドするには便利ですよ。

    • 回答としてマーク taokato 2013年5月16日 5:42
    2013年5月16日 1:38
  • DataGridViewはDataSourceへオブジェクトがセットされた段階で、そのオブジェクトの描写を行います。ただし、既に設定されているオブジェクトと同じオブジェクトをセットしても描写を行いません。今回掲載されているコードでは、Loadイベントでstudentsをセットしてしまっているため、Button調査_Clickイベントハンドラでstudentsをセットしても描写が行われないわけです。
    よって、この状況を回避するために、DataSourceに一度students以外のものをセットすれば良いことになります。この場合は以下のようにNothingが適切でしょう。

    DataGridView1.DataSource = Nothing
    DataGridView1.DataSource = students

    違う方法としては、DataGridView1に再描写をさせれば良いわけですから、
    DataGridView1.Refresh()や、
    DataGridView1.Invalidate()
    を実行すれば良いでしょう。

    ちなみに配列はバインドには向きません。なぜなら、配列に変更があったことをバインド先に教えることができないからです。教えることができれば、DataGridView側で、Refresh()やInvalidate()などで再描写する必要が無くなります。
    例えば、IBindingListを実装しているBindingListなどを配列の代わりに使用すれば良いでしょう。



    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/


    2013年5月16日 1:38
    モデレータ
  • 魔界の仮面弁士 様

    お世話になっております。

    >スクロールしたり、フォームを画面外までドラッグすることでも表示されませんか?

    スクロールで、表示されました。

    >DataSetで管理したほうが、データバインドするには便利ですよ。

    ありがとう御座います。 DataSetでも調査してみます。

    2013年5月16日 5:45
  • trapemiya 様

    ご回答を頂きましてありがとう御座います。

    >IBindingListを実装しているBindingListなどを配列の代わりに使用すれば良いでしょう。

    この辺は、勉強不足で知らないところであります。調査をして組み込んでみたいと思います。

    2013年5月16日 5:48