Hatena::Groupmediaforcelabs

御手洗の開発記録

 | 

2009-12-10

Row展開処理メモ 第一弾-DataGridの編集モードに注意

| 11:30

こんにちは。

御手洗です。

DataGridのRowを展開する処理を実装しました。

DataGridのRowを展開というのは以下のような画面です。

まずは、通常の画面。

f:id:mitarai2009:20091210112107p:image

このDataGridの初めのCellをクリックするとRowが展開されて明細行が表示されます。

f:id:mitarai2009:20091210112104p:image

こんな感じの画面を作ってみました。

ちょっと画面イメージは変わってしまいますが、RowDetailsTemplateを使っても行詳細を表示することができるので、こんなめんどくさいことやりたくないと思う方はそちらを利用してください。

参考URLhttp://msdn.microsoft.com/ja-jp/library/cc903938(VS.95).aspx

今回は、この画面を実装中に困ったことシリーズ第一弾(全二回)をブログに残しておこうと思います。

この処理は、一番最初のCellをクリックした際に、関係のあるCellの高さを変更しています。

private void OpenMonthlyReportGrid(
    DataGrid dataGrid,
    DataGridPreparingCellForEditEventArgs e,
    MonthlyReportItem item)
{
    e.Row.Height = 30 + (item.WorkTimeDetailList.Count * 32);
    item.ExpandFlag = true;
    Grid dateGrid = (Grid)dataGrid.Columns[0].GetCellContent(e.Row);
    dateGrid.RowDefinitions[1].Height = GridLength.Auto;

    Grid projectGrid = (Grid)dataGrid.Columns[1].GetCellContent(e.Row);
    projectGrid.RowDefinitions[1].Height = GridLength.Auto;

    Grid workTimeGrid = (Grid)dataGrid.Columns[2].GetCellContent(e.Row);
    workTimeGrid.RowDefinitions[1].Height = GridLength.Auto;

    Grid subTotalGrid = (Grid)dataGrid.Columns[3].GetCellContent(e.Row);
    subTotalGrid.RowDefinitions[1].Height = GridLength.Auto;
}

GetCellContentを使用して基底パネル(Gridパネル)を取得し、高さを変更しています。

閉じるほうはこんな感じ。

private void CloseMonthlyReportGrid(
    DataGrid dataGrid,
    DataGridPreparingCellForEditEventArgs e,
    MonthlyReportItem item)
{
    e.Row.Height = 30;
    dataGrid.RowHeight = 30;
    item.ExpandFlag = false;
    Grid dateGrid = (Grid)dataGrid.Columns[0].GetCellContent(e.Row);
    dateGrid.RowDefinitions[1].Height = new GridLength(0);

    Grid projectGrid = (Grid)dataGrid.Columns[1].GetCellContent(e.Row);
    projectGrid.RowDefinitions[1].Height = new GridLength(0);

    Grid workTimeGrid = (Grid)dataGrid.Columns[2].GetCellContent(e.Row);
    workTimeGrid.RowDefinitions[1].Height = new GridLength(0);

    Grid subTotalGrid = (Grid)dataGrid.Columns[3].GetCellContent(e.Row);
    subTotalGrid.RowDefinitions[1].Height = new GridLength(0);
}

ここで注意していただきたいのは以下の箇所です。

    dataGrid.RowHeight = 30;

この処理がないと、一度展開したRowの高さがそのままになってしまい、展開していない場合の高さに戻りません。

この処理があるだけで全体のRowの高さを展開していない場合の高さに戻せます。

この処理を行っても、既に展開しているRowの高さが変わることはありません。

多分、Rowの高さはDataGridRowクラスのHeightを優先しているからだと思いますが、今後実装が変わった場合(Silverlight4になる。など)動きが変わってしまうかもしれないので注意する必要がありますね。

今回ブログにメモしておきたかったのはこのことではありません。

その内容は以下に記載します。

DataGridの編集モードに注意

はじめ、この画面を実装したときにCellをクリックして高さを変更しているにも関わらず内部のGridパネルが変更してくれませんでした。

こんな感じになっちゃいます。

f:id:mitarai2009:20091210112731p:image

初めのCellが展開される前と変わっていないのがわかると思います。

自分が最初にハマったときとちょっと動きは違うのですが、原因は同じです。

原因はCellの編集モードにありました。

Cellクリックすると編集モードになります。

Rowの高さを変える処理もその編集モードになる際のイベントで処理を行っています。(自分がハマったときはBeginningEditイベントに処理を追加していました。)

編集モードになると編集モード用のDataTemplateを使用するのですが、今回は指定していなかったので問題なく動作するはずだと思っていました。

しかし、指定していなくても同じインスタンスのDataTemplateを使用しているのではなく、同じDataTemplateで別のインスタンスを利用しているみたいなんです。

なので、編集モード用のDataTemplateインスタンスが適用され、高さ変更がうまくいきませんでした。

これを解決するためにとった方法は、Cellの編集モードをキャンセルする方法です。

ReadOnlyにしてしまうと編集イベントが取れないのでこの方法にしました。

実装したソースは以下の通りです。

private void monthlyReportGrid_PreparingCellForEdit(
    object sender,
    DataGridPreparingCellForEditEventArgs e)
{
    DataGrid dataGrid = (DataGrid)sender;
    if (e.Column.DisplayIndex == 0)
    {
        dataGrid.CancelEdit();
        ExpandMonthlyReportGrid(dataGrid, e);
    }
}

BeginningEditイベントではキャンセル処理がうまく動作しなかったので、PreparingCellForEditイベントになっています。

編集モードに移行したCellが0番目だった場合(初めのCell)、DataGridのCancelEdit()メソッドで編集モードをキャンセルしています。

この後に、Rowの高さを変更するとうまく動作してくれました。

まとめ

ソースを調べていないのではっきりしたことは言えませんが、編集モードのDataTemplateを指定していなくても編集モードに切り替わると別のインスタンスになるので注意してください。




ということで、次回に続きます。

LhilLhil2012/03/23 04:58I'm not easliy impressed but you've done it with that posting.

jwrbtxjwrbtx2012/03/23 15:55QvGCzg <a href="http://fdsqbxvuohwc.com/">fdsqbxvuohwc</a>

chwhzuptchwhzupt2012/03/23 18:52uGrs7H , [url=http://zvyjjesojtgp.com/]zvyjjesojtgp[/url], [link=http://xrjmffqaogkt.com/]xrjmffqaogkt[/link], http://ttedrtjlooto.com/

 |