none
DataGridView でデータを 2 次元的に配置し、かつ連結も保持したい RRS feed

  • 質問

  • 図 1 のようなデータを収めたテーブルを用意します。

    図 1 : DataTable 内のデータ



    これを DataGridView で簡単に表示しようとすると、
    DataTable -> BindingSource -> DataGridView のように接続されて、
    テーブルの内容が縦方向 (列方向) に列挙されます。
    (図 2 左側 DataGridView-A)


    図 2 : DataTable のデータを DataGridView で表示
    DataGridView-A : 縦方向に列挙 (通常表示)
    DataGridView-B : 縦横に 2 次元的に列挙





    では、これを縦横、2次元的に配置するにはどうすればよいのでしょう?
    但し、DataTable から DataGridView までの連結は保持したままで。

    (図 2 右側 DataGridView-B)



    図 2 の DataGridView-B は、
    DataTable の id, name の name のみを表示していると考えてください。

    DataGridView-B でセル内の値が変更されると、
    該当する DataTable のデータも変更されるようにしたいと考えています。

    通常、BindingSource が DataGridView の各 Row にどのようにして Binding されているか
    を参考にできないか、と考えています。

    2009年3月23日 0:41

回答

  • DataGridView_BをVirtualModeにしてしまえば簡単にできましたが。
    VirtualModeの使用は不可?

    とちあえずの手抜きコード

    1 public class LinkMatrixView : DataGridView 
    2
    3     public LinkMatrixView() : base() 
    4     { 
    5         TargetColumnIndex = 0; 
    6         this.VirtualMode=true
    7         LinkDataGridView = null
    8  
    9         // 追加は面倒そうだからとりあえず無視 
    10         this.AllowUserToAddRows = false
    11     } 
    12  
    13     /// <summary>リンクさせるソースの設定</summary> 
    14     public void SetLink(DataGridView grid , int columnIndex) 
    15     { 
    16         BindingSource source = grid.DataSource as BindingSource; 
    17         if (source == null
    18         { 
    19             throw new ApplicationException("DataGridのDataSourceにはBindingSourceを設定しておいてください"); 
    20         } 
    21         else 
    22         { 
    23             this.TargetColumnIndex = columnIndex; 
    24             this.LinkDataGridView = grid; 
    25         } 
    26     } 
    27  
    28     public int TargetColumnIndex { get;private set; } 
    29  
    30     /// <summary>リンクさせるDataGridView</summary>    
    31     public DataGridView LinkDataGridView 
    32     { 
    33         get 
    34         { 
    35             return _LinkDataGridView; 
    36         } 
    37         private set 
    38         { 
    39             const int ROWCOUNT_B = 10; 
    40  
    41             this.Columns.Clear(); 
    42             if (_LinkDataGridView != null
    43             { 
    44                 LinkSource.CurrentChanged -= Source_CurrentChanged; 
    45                 LinkSource.CurrentItemChanged -= Source_CurrentItemChanged; 
    46             } 
    47             _LinkDataGridView = value; 
    48             if (value != null
    49             { 
    50                 DataGridViewColumn clm; 
    51                 int columnCount; 
    52                 columnCount = (int)Math.Ceiling((double)LinkSource.Count  / ROWCOUNT_B); 
    53                 for (int idx = 0; idx < columnCount; idx++) 
    54                 { 
    55                     //DataGridView_Aの列の設定をコピーしてDataGridView_Bの列を作る 
    56                     clm = (DataGridViewColumn)LinkDataGridView.Columns[TargetColumnIndex].Clone(); 
    57                     clm.HeaderText = clm.Name = idx.ToString() + "列目"
    58                     this.Columns.Add(clm); 
    59                 } 
    60  
    61                 // DataGridView_Bの表示行数を指定 
    62                 this.RowCount = ROWCOUNT_B; 
    63  
    64                 LinkSource.CurrentChanged += Source_CurrentChanged; 
    65                 LinkSource.CurrentItemChanged += Source_CurrentItemChanged; 
    66             } 
    67         } 
    68     } 
    69     private DataGridView _LinkDataGridView; 
    70  
    71     /// <summary> 
    72     /// リンクされているBindingSource 
    73     /// </summary> 
    74     private BindingSource LinkSource 
    75     { 
    76         get { return LinkDataGridView.DataSource as BindingSource; } 
    77     } 
    78  
    79  
    80     void Source_CurrentItemChanged(object sender , EventArgs e) 
    81     { 
    82         //TODO: どうやるのか後で考える 
    83     } 
    84  
    85     void Source_CurrentChanged(object sender , EventArgs e) 
    86     { 
    87         this.Refresh(); 
    88     } 
    89  
    90  
    91  
    92     /// <summary>DataGridViewの各セルに表示する値が要求された</summary> 
    93     protected override void OnCellValueNeeded(DataGridViewCellValueEventArgs e) 
    94     { 
    95         //base.OnCellValueNeeded(e); 
    96         int idx; 
    97         idx = e.RowIndex + e.ColumnIndex * this.RowCount; 
    98         if (LinkSource != null && idx < LinkSource.Count) 
    99         { 
    100             // BindingSourceから値を取り出す 
    101             e.Value = ((DataRowView)LinkSource[idx])[TargetColumnIndex]; 
    102         } 
    103     } 
    104  
    105     /// <summary>DataGridViewのセルの値が変更された</summary> 
    106     protected override void OnCellValuePushed(DataGridViewCellValueEventArgs e) 
    107     { 
    108         //base.OnCellValuePushed(e); 
    109         int idx; 
    110         idx = e.RowIndex + e.ColumnIndex * this.RowCount; 
    111         if (LinkSource != null && idx < LinkSource.Count) 
    112         { 
    113             // BindingSourceに値をいれる 
    114             ((DataRowView)LinkSource[idx])[TargetColumnIndex] = e.Value; 
    115         } 
    116     } 
    117  
    118     /// <summary>DataGridViewの選択されているセル位置が変わった</summary> 
    119     protected override void OnCurrentCellChanged(EventArgs e) 
    120     { 
    121         base.OnCurrentCellChanged(e); 
    122  
    123             int idx; 
    124             DataGridViewCell cell = this.CurrentCell; 
    125             if (cell != null
    126             { 
    127                 idx = this.RowCount * cell.ColumnIndex + cell.RowIndex; 
    128                 if (LinkSource != null
    129                 { 
    130                     LinkSource.Position = this.RowCount * cell.ColumnIndex + cell.RowIndex; 
    131                 } 
    132             } 
    133          
    134     } 
    135  
    136
    137  
    138 namespace WindowsFormsApplication1 
    139
    140     public partial class Form1 : Form 
    141     { 
    142         public Form1() 
    143         { 
    144             InitializeComponent(); 
    145  
    146             //省略しますがDataTable1にはString型の列が2列あってDataGridView_AのデータソースにBindingSourceで設定してあります。 
    147         } 
    148  
    149         private void Form1_Load(object sender , EventArgs e) 
    150         { 
    151             ///とりあえずテストデータを作ってみる 
    152             DataRow row; 
    153             System.Random rnd = new Random(); 
    154             for (int idx = 0; idx < 23; idx++) 
    155             { 
    156                 row = dataSet1.DataTable1.NewRow(); 
    157                 row[0] = rnd.Next().ToString(); 
    158                 row[1] = idx.ToString(); 
    159                 dataSet1.DataTable1.Rows.Add(row); 
    160             } 
    161  
    162             // LinkMatrixViewにソースを設定 
    163             DataGridView_B.SetLink(this.DataGridView_A , 1); 
    164         } 
    165     } 
    166


    #眠いのでここまで
    • 回答としてマーク custar 2009年3月26日 4:43
    2009年3月23日 18:19

すべての返信

  • custarさん の発言:

    通常、BindingSource が DataGridView の各 Row にどのようにして Binding されているか
    を参考にできないか、と考えています。

    ADO.NETにしてもBindingSourceにしても、データテーブルの1行が処理単位になっていますので、残念ながらまず間違いなく無理だと思います。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年3月23日 5:43
    モデレータ
  • trapemiya さんの発言:

    データテーブルの1行が処理単位になっていますので、
    残念ながらまず間違いなく無理だと思います。


    trapemiya さん、お久し振りです。

    行への処理が基本的な処理だということは、その通りだと思います。
    ただ、

    • 2次元の DataGridView のセルを 1次元 (縦方向) に並べたと仮定
    • 拡張 DataGridView への新規プロパティ (Position) の追加
    • 拡張 BindingSource への新規プロパティ (XPosition) の追加
    • 両プロパティを結びつけ
    • Binding の Parse/Format で細工

    で何かしらできないか、暫くやってみましたが困難で、挫折です。
    しばし保留してみます。

    trapemiya さん、アドバイス、ありがとうございました。
    2009年3月23日 14:33
  • >trapemiya さん、お久し振りです。

    こちらこそ。

    ところで、もしやるとしたら、1次元と2次元のデータテーブルをバインド(マッピング)するような仕組みを構築し、その2次元のデータテーブルを通常のBindingSourceに結びつけた方が簡単かもしれません。

    dataTable <- マッピング -> 2次元dataTable <-> BindingSource <-> DataGridView


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年3月23日 14:52
    モデレータ
  • DataGridView_BをVirtualModeにしてしまえば簡単にできましたが。
    VirtualModeの使用は不可?

    とちあえずの手抜きコード

    1 public class LinkMatrixView : DataGridView 
    2
    3     public LinkMatrixView() : base() 
    4     { 
    5         TargetColumnIndex = 0; 
    6         this.VirtualMode=true
    7         LinkDataGridView = null
    8  
    9         // 追加は面倒そうだからとりあえず無視 
    10         this.AllowUserToAddRows = false
    11     } 
    12  
    13     /// <summary>リンクさせるソースの設定</summary> 
    14     public void SetLink(DataGridView grid , int columnIndex) 
    15     { 
    16         BindingSource source = grid.DataSource as BindingSource; 
    17         if (source == null
    18         { 
    19             throw new ApplicationException("DataGridのDataSourceにはBindingSourceを設定しておいてください"); 
    20         } 
    21         else 
    22         { 
    23             this.TargetColumnIndex = columnIndex; 
    24             this.LinkDataGridView = grid; 
    25         } 
    26     } 
    27  
    28     public int TargetColumnIndex { get;private set; } 
    29  
    30     /// <summary>リンクさせるDataGridView</summary>    
    31     public DataGridView LinkDataGridView 
    32     { 
    33         get 
    34         { 
    35             return _LinkDataGridView; 
    36         } 
    37         private set 
    38         { 
    39             const int ROWCOUNT_B = 10; 
    40  
    41             this.Columns.Clear(); 
    42             if (_LinkDataGridView != null
    43             { 
    44                 LinkSource.CurrentChanged -= Source_CurrentChanged; 
    45                 LinkSource.CurrentItemChanged -= Source_CurrentItemChanged; 
    46             } 
    47             _LinkDataGridView = value; 
    48             if (value != null
    49             { 
    50                 DataGridViewColumn clm; 
    51                 int columnCount; 
    52                 columnCount = (int)Math.Ceiling((double)LinkSource.Count  / ROWCOUNT_B); 
    53                 for (int idx = 0; idx < columnCount; idx++) 
    54                 { 
    55                     //DataGridView_Aの列の設定をコピーしてDataGridView_Bの列を作る 
    56                     clm = (DataGridViewColumn)LinkDataGridView.Columns[TargetColumnIndex].Clone(); 
    57                     clm.HeaderText = clm.Name = idx.ToString() + "列目"
    58                     this.Columns.Add(clm); 
    59                 } 
    60  
    61                 // DataGridView_Bの表示行数を指定 
    62                 this.RowCount = ROWCOUNT_B; 
    63  
    64                 LinkSource.CurrentChanged += Source_CurrentChanged; 
    65                 LinkSource.CurrentItemChanged += Source_CurrentItemChanged; 
    66             } 
    67         } 
    68     } 
    69     private DataGridView _LinkDataGridView; 
    70  
    71     /// <summary> 
    72     /// リンクされているBindingSource 
    73     /// </summary> 
    74     private BindingSource LinkSource 
    75     { 
    76         get { return LinkDataGridView.DataSource as BindingSource; } 
    77     } 
    78  
    79  
    80     void Source_CurrentItemChanged(object sender , EventArgs e) 
    81     { 
    82         //TODO: どうやるのか後で考える 
    83     } 
    84  
    85     void Source_CurrentChanged(object sender , EventArgs e) 
    86     { 
    87         this.Refresh(); 
    88     } 
    89  
    90  
    91  
    92     /// <summary>DataGridViewの各セルに表示する値が要求された</summary> 
    93     protected override void OnCellValueNeeded(DataGridViewCellValueEventArgs e) 
    94     { 
    95         //base.OnCellValueNeeded(e); 
    96         int idx; 
    97         idx = e.RowIndex + e.ColumnIndex * this.RowCount; 
    98         if (LinkSource != null && idx < LinkSource.Count) 
    99         { 
    100             // BindingSourceから値を取り出す 
    101             e.Value = ((DataRowView)LinkSource[idx])[TargetColumnIndex]; 
    102         } 
    103     } 
    104  
    105     /// <summary>DataGridViewのセルの値が変更された</summary> 
    106     protected override void OnCellValuePushed(DataGridViewCellValueEventArgs e) 
    107     { 
    108         //base.OnCellValuePushed(e); 
    109         int idx; 
    110         idx = e.RowIndex + e.ColumnIndex * this.RowCount; 
    111         if (LinkSource != null && idx < LinkSource.Count) 
    112         { 
    113             // BindingSourceに値をいれる 
    114             ((DataRowView)LinkSource[idx])[TargetColumnIndex] = e.Value; 
    115         } 
    116     } 
    117  
    118     /// <summary>DataGridViewの選択されているセル位置が変わった</summary> 
    119     protected override void OnCurrentCellChanged(EventArgs e) 
    120     { 
    121         base.OnCurrentCellChanged(e); 
    122  
    123             int idx; 
    124             DataGridViewCell cell = this.CurrentCell; 
    125             if (cell != null
    126             { 
    127                 idx = this.RowCount * cell.ColumnIndex + cell.RowIndex; 
    128                 if (LinkSource != null
    129                 { 
    130                     LinkSource.Position = this.RowCount * cell.ColumnIndex + cell.RowIndex; 
    131                 } 
    132             } 
    133          
    134     } 
    135  
    136
    137  
    138 namespace WindowsFormsApplication1 
    139
    140     public partial class Form1 : Form 
    141     { 
    142         public Form1() 
    143         { 
    144             InitializeComponent(); 
    145  
    146             //省略しますがDataTable1にはString型の列が2列あってDataGridView_AのデータソースにBindingSourceで設定してあります。 
    147         } 
    148  
    149         private void Form1_Load(object sender , EventArgs e) 
    150         { 
    151             ///とりあえずテストデータを作ってみる 
    152             DataRow row; 
    153             System.Random rnd = new Random(); 
    154             for (int idx = 0; idx < 23; idx++) 
    155             { 
    156                 row = dataSet1.DataTable1.NewRow(); 
    157                 row[0] = rnd.Next().ToString(); 
    158                 row[1] = idx.ToString(); 
    159                 dataSet1.DataTable1.Rows.Add(row); 
    160             } 
    161  
    162             // LinkMatrixViewにソースを設定 
    163             DataGridView_B.SetLink(this.DataGridView_A , 1); 
    164         } 
    165     } 
    166


    #眠いのでここまで
    • 回答としてマーク custar 2009年3月26日 4:43
    2009年3月23日 18:19
  • trapemiya さんの発言:

    1次元と2次元のデータテーブルをバインド(マッピング)するような仕組みを構築し、
    その2次元のデータテーブルを通常のBindingSourceに結びつけた方が簡単かもしれません。

    {Column|Row}Count は固定ですので可能だと思います。
    似たようなことを考えていたのですが、
    ただ、ずばりストレートに行かないなぁというのを思っていました。
    # Binding の方が簡単そうに思えたので先にやったのですが、疲れ果てました。

    2009年3月23日 18:50
  • gekka さんの発言:

    DataGridView_BをVirtualModeにしてしまえば簡単にできましたが。
    VirtualModeの使用は不可?


    えぇ、出来たんですか?

    不可ではありません。

    VirtualMode ? 何かな、それは?
    沢山のデータを扱う時に使うものじゃなかったのかな.....?
    という 1 年前のかすかな記憶がある程度ですので、
    VirtualMode が使えるとは思いませんでした。

    こんな時刻ですし、私も眠いので明日追試してみます。

    2009年3月23日 18:58
  •  直接バインドするのは無理ですが、何らかの方法でマッピングすれば間接的にバインドすることは可能でしょう。マッピングに関しては私が先に述べたデータテーブル間のマッピング、gekkaさんのDataGridViewとBindingSource間でのマッピング、それからcustarさんが試されている拡張BindingSourceのようにIBindingListViewなどを実装したクラスの作成の3種類だと思います。
    私は先にデータテーブル間のマッピングの方を先に考えたのですが(理由:DataGridViewやBindingSourceを普通に使えるため自由度が高く、汎用的であり、拡張BindingSourceの実現より簡単そう)、gekkaさんのコードも大変参考になりました。

    理想的には拡張BindingSourceの方向なんでしょうが、以下を参考にして実現できるかもしれません。

    カスタム データ バインド (第 2 部)
    http://msdn.microsoft.com/ja-jp/library/ms993236.aspx

    #拡張BindingSourceというかIBindingListViewを実装したクラスを使えば、データテーブルを2次元に展開してDataGridViewに直接バインドできると言えるでしょう。そういう意味で、最初の「直接バインドするのは無理ですが」と言った私の記述は正確ではありませんね。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年3月24日 3:00
    モデレータ
  • 方法 : Windows フォーム DataGridView コントロールで仮想モードを実装する
    • VirtualMode プロパティが true の場合、
    • 設定された行数および列数の DataGridView を作成してから、
    • CellValueNeeded イベントを使用してセルを設定します。
    なるほど、勝手に表示させないようにするんですね。

    仮想モードでは、

    1. 基になるデータ キャッシュを実装して、
    2. ユーザーの操作に基づき DataGridView セルの
      • 読み込み
      • 編集
      • 削除

    を処理する必要があります。

    - 方法 : Windows フォーム DataGridView コントロールで仮想モードを実装する

    を参照すると、DataGridView の下記イベントが設定されています。

    1. CellValueNeeded
    2. CellValuePushed
    3. NewRowNeeded
    4. RowValidated
    5. RowDirtyStateNeeded
    6. CancelRowEdit
    7. UserDeletingRow

    NewRowNeeded, UserDeletingRow は今回不要。

    (1) CellValueNeeded
    • DataGridView コントロールの VirtualMode プロパティが true で
    • セルを書式設定して表示するために
    • DataGridView がセルの値を必要とする場合に発生

    Binding の Format ですね。

    (2) CellValuePushed
    • DataGridView コントロールの VirtualMode プロパティが true で
    • セルの値が変更され、
    • 基になるデータ ソースに格納する必要がある場合に発生

    Binding の Parse ですね。

    (3) NewRowNeeded
    • DataGridView の VirtualMode プロパティが true で
    • ユーザーが DataGridView の下部にある新しい行に移動したときに発生

    (4) RowValidated
    • 行が検証を完了した後に発生
     
    (5) RowDirtyStateNeeded
    • DataGridView コントロールの VirtualMode プロパティが true で
    • DataGridView が現在の行にコミットされていない変更の有無を確認する必要がある場合に発生
     
    (6) CancelRowEdit
    • DataGridView コントロールの VirtualMode プロパティが true で
    • 行の編集をキャンセルした場合に発生

    (7) UserDeletingRow
    • ユーザーが DataGridView コントロールから行を削除するときに発生
     

    ふむふむ。


    + 追記
    ---
    gekka さんのやられていることは理解しましたので、現在試行中。

    2009年3月24日 6:56
  • gekka さんに、"VirtualMode" というヒントをいただいたので、
    下記ドキュメントに目を通しました。

    - チュートリアル : Windows フォーム DataGridView コントロールでの仮想モードの実装 

    チュートリアルは gekka さんのとは "書き方" は違うけど
    おそらくやってることは同じだと思うので、
    チュートリアルの書き方ではどうなるかを試してみました。

    結果はこんな感じです。

    (C) ... 母音のテーブル
    (D) ... 子音のテーブル
    (E) ... 50音のテーブル
    (F) ... gekka さんのコードを元に作成した Grid
    (E) ... チュートリアルを参考に作った Grid

    (F),(E) では、縦に母音、横に子音で分類して表示させています。

    (G) でセルを編集すると、
    (E) の対応するセルの値も変更されます。
    下図では "a,i,u,e,o" を「あ、い、う、え、お」に書き換えています。



    以下のような設定で表示できるようにしました。

    1 this.arrangedGridView1.DisplayName    = "name";  
    2 this.arrangedGridView1.DataMember     = "chars";  
    3 this.arrangedGridView1.PrimaryParent  = "vowels";  
    4 this.arrangedGridView1.DataSource     = this.database1DataSet; 

    DisplayName で表示させたい値を指定。

    列数と行数を自動で生成させたかったので、
    Relation を取れるように DataSet を DataSource に割り当てるようにしました。
    そのため、DataMember で DataTable を指定。

    PrimaryParent で縦側をどの親に割り当てるかを指定。

    ソースコードは以下の通りです。
    取り敢えず動くようにしただけですので、
    間違いや不適当な部分があったらご指摘ください。
    # こちらの都合に合わせた決め打ちな部分もあります。


    1 public partial class ArrangedGridView : DataGridView  
    2 {  
    3   private bool __rowScopeCommit = true;  
    4   private string __primaryParent = string.Empty;  
    5   private string __displayName = "name";  
    6   private DataSet __dataSet;  
    7  
    8   public ArrangedGridView() : base()  
    9   {  
    10     InitializeComponent();  
    11     this.__rowScopeCommit = false;  
    12   }  
    13  
    14   public new object DataSource  
    15   {  
    16     get { return this.bs; }  
    17     set 
    18     {  
    19       if (value != null && value is DataSet)  
    20       {  
    21         this.__dataSet = value as DataSet;  
    22  
    23         if (!string.IsNullOrEmpty(this.DataMember))  
    24         {  
    25           this.bs.DataMember = this.DataMember;  
    26           this.bs.DataSource = this.__dataSet;  
    27           this.__makeGrid();  
    28         }  
    29         else 
    30         {  
    31           throw new ApplicationException(this.Name + ": DataMember ....");  
    32         }  
    33       }  
    34       else 
    35       {  
    36         throw new ApplicationException(this.Name + ": DataSource ....");  
    37       }  
    38     }  
    39   }  
    40  
    41   public string DisplayName  
    42   {  
    43     get { return this.__displayName; }  
    44     set 
    45     {  
    46       if (!string.IsNullOrEmpty(value))  
    47       {  
    48         this.__displayName = value;  
    49         this.__makeGrid();  
    50       }  
    51     }  
    52   }  
    53  
    54   public string PrimaryParent  
    55   {  
    56     get { return this.__primaryParent; }  
    57     set 
    58     {  
    59       if (!string.IsNullOrEmpty(value))  
    60       {  
    61         this.__primaryParent = value;  
    62       }  
    63     }  
    64   }  
    65  
    66   private void __makeGrid()  
    67   {  
    68     if (this.__dataSet != null)  
    69     {  
    70       this.Columns.Clear();  
    71       DataTable table = this.__dataSet.Tables[this.DataMember];  
    72  
    73       if (table.ParentRelations.Count == 2)  
    74       {  
    75         DataTable parent;  
    76         foreach (DataRelation rel in table.ParentRelations)  
    77         {  
    78           parent = rel.ParentTable;  
    79  
    80           if (string.IsNullOrEmpty(this.__primaryParent))  
    81           {  
    82             this.__primaryParent = parent.TableName;  
    83           }  
    84  
    85           if (this.__primaryParent == parent.TableName)  
    86           {  
    87             this.RowCount = parent.Rows.Count;  
    88           }  
    89           else 
    90           {  
    91             this.ColumnCount = parent.Rows.Count;  
    92  
    93             DataGridViewColumn col;  
    94             int colIndex = 0;  
    95             foreach (DataRow row in parent.Rows)  
    96             {  
    97               col = this.Columns[colIndex++];  
    98               col.Name = col.HeaderText = row["name"].ToString();  
    99               col.Width = 50;  
    100             }  
    101           }  
    102         }  
    103       }  
    104     }  
    105   }  
    106  
    107   private int __getPosition(int colIndex, int rowIndex)  
    108   {  
    109     return rowIndex + colIndex * this.RowCount;  
    110   }  
    111  
    112   private void ArrangedGrid_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)  
    113   {  
    114     int idx = this.__getPosition(e.ColumnIndex, e.RowIndex);  
    115  
    116     if (this.bs != null && idx < this.bs.Count)  
    117     {  
    118       e.Value = ((DataRowView)this.bs[idx])[this.DisplayName];  
    119     }  
    120   }  
    121  
    122   private void ArrangedGrid_CellValuePushed(object sender, DataGridViewCellValueEventArgs e)  
    123   {  
    124     int idx = this.__getPosition(e.ColumnIndex, e.RowIndex);  
    125  
    126     if (this.bs != null && idx < this.bs.Count)  
    127     {  
    128       ((DataRowView)bs[idx])[this.DisplayName] = e.Value;  
    129     }  
    130   }  
    131  
    132   private void ArrangedGrid_RowValidated(object sender, DataGridViewCellEventArgs e)  
    133   {  
    134     int idx = this.__getPosition(e.ColumnIndex, e.RowIndex);  
    135  
    136     if (this.bs != null && idx < this.bs.Count)  
    137     {  
    138       ((DataRowView)this.bs[idx])[this.DisplayName] = this[e.ColumnIndex, e.RowIndex].Value;  
    139     }  
    140   }  
    141  
    142   private void ArrangedGrid_RowDirtyStateNeeded(object sender, QuestionEventArgs e)  
    143   {  
    144     if (!this.__rowScopeCommit)  
    145     {  
    146       e.Response = this.IsCurrentCellDirty;  
    147     }  
    148   }  
    149  
    150   private void ArrangedGrid_CurrentCellChanged(object sender, EventArgs e)  
    151   {  
    152     DataGridViewCell cell = this.CurrentCell;  
    153       
    154     if (cell != null)  
    155     {  
    156       if (this.bs != null)  
    157       {  
    158         this.bs.Position = this.RowCount * cell.ColumnIndex + cell.RowIndex;  
    159       }   
    160     }  
    161   }  
    162
    2009年3月24日 15:35
  • bind された DataGridView は行の並べ替えができないけど、

    VirtualMode だと、
    もしかしたらできないか?と思い試しています。

    行移動のための、行の削除と挿入が思い通りにならない....

    2009年3月25日 5:50
  • trapemiya さんの発言:

    カスタム データ バインド (第 2 部)
    http://msdn.microsoft.com/ja-jp/library/ms993236.aspx

    短いドキュメントなのでさらりと読めそうです。


    1 つの解決策が見つかったので、一旦本スレッドを閉じたいと思います。

    trapemiya さんの提案と、私の案は以後私の理解度に合わせて実装していきた
    いと思います。ですので、進展があり次第、ここに挙げたいと思います。


    trapemiya さん、gekka さん、情報ありがとうございます。
    2009年3月26日 4:40