わいえむねっと

Contents
Categories
Calendar
2010/04
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30
Monthly Archives
~2000/01
Recent Entries
RSS1.0
Templates
Information
Processed: 0.033 sec
Chashed: -
2010/04/10 Sat
・構造が同一の2つのDataTableが存在
・1対1のデータが格納
・一方をDataGridViewの表示に、一方をRowFilterとSortの条件に使用

しているコードがあって、ぼけと眺めてみたところ、

・2つのDataTableをマージ
・カラム名は重複を避けて識別子を付与
・識別子を適宜切り替えてアクセス

とかいうことをしていたので、マージとかせずにDataSetで管理できないのかなーと思ったので試してみる。
あと、DataViewのRowFilterとSortは即時反映のため、DataGridViewへの入力を確定した瞬間に行が消えたり移動したりするので、これもどうにかしたい。

とりあえず、RowFilterとSortから参照するためだけの管理列を追加してみる。

DataTable table1 = new DataTable();
table1.Columns.Add("A");
table1.Columns.Add("B");
table1.Columns.Add("Z");
table1.Rows.Add(1, "foo", 1);
table1.Rows.Add(2, "bar", 2);
table1.Rows.Add(3, "baz", 3);
table1.AcceptChanges();

DataTable table2 = new DataTable();
table2.Columns.Add("A");
table2.Columns.Add("B");
table2.Rows.Add(1, "FOO");
table2.Rows.Add(2, "BAR");
table2.Rows.Add(3, "BAZ");
table2.AcceptChanges();

DataSet dataSet = new DataSet();
dataSet.Tables.Add(table1);
dataSet.Tables.Add(table2);
dataSet.Relations.Add(new DataRelation("rel",
    table1.Columns["A"],
    table2.Columns["A"]));

DataView dataView = new DataView(
    table1, "Z > 0", "Z", DataViewRowState.CurrentRows);
//DataGridView.DataSource = dataView;
//DataGridView.Columns["Z"].Visible = false;

foreach (DataRowView rowView in dataView)
{
    Debug.Print(rowView.Row["B"].ToString() + " " +
        rowView.Row.RowState.ToString() + " " +
        rowView.Row.GetChildRows("rel")[0]["B"].ToString() + " " +
        rowView.Row.GetChildRows("rel")[0].RowState.ToString());
}
//foo Unchanged FOO Unchanged
//bar Unchanged BAR Unchanged
//baz Unchanged BAZ Unchanged

foreach (DataRow row in table1.Rows)
{
    row["Z"] = 0;
}
int i = 1;
foreach (DataRowView rowView in new DataView(
    table2, "B LIKE 'B*'", "B DESC", DataViewRowState.CurrentRows))
{
    rowView.Row.GetParentRow("rel")["Z"] = i;
    i++;
}

foreach (DataRowView rowView in dataView)
{
    Debug.Print(rowView.Row["B"].ToString() + " " +
        rowView.Row.RowState.ToString() + " " +
        rowView.Row.GetChildRows("rel")[0]["B"].ToString() + " " +
        rowView.Row.GetChildRows("rel")[0].RowState.ToString());
}
//baz Modified BAZ Unchanged
//bar Modified BAR Unchanged

RowFilterとSortの反映タイミングは列Zの更新タイミングで制御可能になったものの、親DataTableのRowStateが軒並みModifiedになってしまうので、DataGridView経由で編集されたかどうかが取得できなくなる。

だったらと、列Zを子側に押し付けて、DataColumn.Expression経由で参照してみる。

DataTable table1 = new DataTable();
table1.Columns.Add("A");
table1.Columns.Add("B");
table1.Rows.Add(1, "foo");
table1.Rows.Add(2, "bar");
table1.Rows.Add(3, "baz");
table1.AcceptChanges();

DataTable table2 = new DataTable();
table2.Columns.Add("A");
table2.Columns.Add("B");
table2.Columns.Add("Z", System.Type.GetType("System.Decimal"));
table2.Rows.Add(1, "FOO", 1);
table2.Rows.Add(2, "BAR", 2);
table2.Rows.Add(3, "BAZ", 3);
table2.AcceptChanges();

DataSet dataSet = new DataSet();
dataSet.Tables.Add(table1);
dataSet.Tables.Add(table2);
dataSet.Relations.Add(new DataRelation("rel",
    table1.Columns["A"],
    table2.Columns["A"]));

table1.Columns.Add("Y");
table1.Columns["Y"].Expression = "Min(Child.Z)";

DataView dataView = new DataView(
    table1, "Y > 0", "Y", DataViewRowState.CurrentRows);
//DataGridView.DataSource = dataView;
//DataGridView.Columns["Y"].Visible = false;

foreach (DataRowView rowView in dataView)
{
    Debug.Print(rowView.Row["B"].ToString() + " " +
        rowView.Row.RowState.ToString() + " " +
        rowView.Row.GetChildRows("rel")[0]["B"].ToString() + " " +
        rowView.Row.GetChildRows("rel")[0].RowState.ToString());
}
//foo Unchanged FOO Unchanged
//bar Unchanged BAR Unchanged
//baz Unchanged BAZ Unchanged

foreach (DataRow row in table2.Rows)
{
    row["Z"] = 0;
}
int i = 1;
foreach (DataRowView rowView in new DataView(
    table2, "B LIKE 'B*'", "B DESC", DataViewRowState.CurrentRows))
{
    rowView.Row["Z"] = i;
    i++;
}

foreach (DataRowView rowView in dataView)
{
    Debug.Print(rowView.Row["B"].ToString() + " " +
        rowView.Row.RowState.ToString() + " " +
        rowView.Row.GetChildRows("rel")[0]["B"].ToString() + " " +
        rowView.Row.GetChildRows("rel")[0].RowState.ToString());
}
//baz Unchanged BAZ Modified
//bar Unchanged BAR Modified

Modifiedにはならないけれど、余計な列がさらに増えたり、Expressionの中身がどうにも直感的にならなかったり。
ままならない。