locked
DataGridのItemsSourceプロパティにデータを格納して、表示が終わった後にイベントハンドラを呼び出す方法について RRS feed

  • 質問

  • Silverlight 4 でDataGridを使ったアプリケーションを作成しています。

    ItemsSourceプロパティにデータを格納して、画面に表示をさせた直後のタイミングでイベントハンドラを呼び出したいのですが、どのようなソースを組めばよいのか分かりません。おそらく、変更通知とかの話ですので、INotifyPropertyChanged を継承したクラスを使うことになるのでしょうが、DataGridコントロールとどのように絡めればよいのか、その辺りが良く分かりません。よろしくお願いいたします。

    2011年9月22日 6:26

回答

  • こんにちは。
    そのDataGridView.csの実装がどうなっているかわからないのでこのケースに当てはまるかはわかりませんが
    一般的なDataGridのお話として言えることは

    DataGridRowは実際に描画される時までインスタンスは作られない
    (AutoGenerateColumnsをTrueにしている場合は自動生成Columnも。)

    ということです。

    質問文のやりかただとすると、
    あるはずの行や列が見つからなくてエラーになっているような気がしますので、

    dataGridView1.DataSource = dt;

    の後に

    DataGrid.UpdateLayout();
    


    を入れてあげるといけるんじゃないかと思います。
    (DataGridView.csがUpdateLayoutメソッドをサポートしているかどうかはわかりませんが)
    2011年10月2日 13:00

すべての返信

  • 質問が漠然としてましたので、ソースを張らせて頂きます。

    string型の2次元配列からDataTable(自作のコード)を作成して、DataGridView(自作のコード、DataGridをラップしている)のDataSourceにセットして、表を表示し、セルに色を付けるところまでを一度に行いたいのですが、(1)のところで例外が発生してしまいます。どこを直せばよいのか教えてください。

    ちなみに、DataGridViewは、SilverlightからDataGridをSystem.Windows.Formsの、DataGridViewのように扱えるようにしたものです。


    --------------------------------
    Admin2.xaml
    --------------------------------

    <UserControl xmlns:basics="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
    x:Class="dg3371.Admin2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:my="clr-namespace:MyDataGridView"
        Width="800" Height="600"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
        <Canvas x:Name="LayoutRoot" Background="White">
            <StackPanel Orientation="Vertical">
                <my:DataGridView HorizontalAlignment="Left" Margin="12,12,0,0"
    x:Name="dataGridView1" VerticalAlignment="Top" Height="280" Width="500" />
                <Button x:Name="Button1" Width="70" Height="30" Content="ロード"
    Click="Button1_Click" />
                <Button x:Name="Button2" Width="70" Height="30" Content="色付け"
    Click="Button2_Click" />
            </StackPanel>
        </Canvas>
    </UserControl>

    --------------------------------
    Admin2.xaml.cs
    --------------------------------

    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.ComponentModel;
    using MyDataGridView;

    namespace dg3371
    {
        public partial class Admin2 : UserControl
        {
            public Admin2()
            {
                InitializeComponent();
            }

            private void Button1_Click(object sender, RoutedEventArgs e)
            {
                int i, j, i_max, j_max;

                i_max = 7;
                j_max = 5;

                string[][] strs = new string[j_max][];

                for (j = 0; j < strs.Length; j++)
                    strs[j] = new string[i_max];

                for (j = 0; j < strs.Length; j++)
                {
                    for (i = 0; i < strs[0].Length; i++)
                    {
                        strs[j][i] = string.Format("str[{0}][{1}]", j, i);
                    }
                }

                DataTable dt;

                dt = new DataTable(strs);
                dataGridView1.DataSource = dt;

                while (true)  ---------- (2)
                {
                    if (dataGridView1.Columns.Count == i_max && dataGridView1.Rows.Count == j_max - 1)
                    {
                        Button2_Click(sender, e);   ---------- (1)
                        break;
                    }
                }
            }

            private void Button2_Click(object sender, RoutedEventArgs e)
            {
                dataGridView1.Rows[0].Cells[0].BackColor = Color.FromArgb(255, 255, 128, 128);
                dataGridView1.Rows[1].Cells[1].BackColor = Color.FromArgb(255, 255, 0, 0);
                dataGridView1.Rows[2].Cells[2].BackColor = Color.FromArgb(255, 255, 0, 0);
                dataGridView1.Rows[3].Cells[3].BackColor = Color.FromArgb(255, 255, 0, 0);
            }
        }
    }

    (2)のwhile文を取り除いて、「ロード」ボタン、「色付け」ボタンを順番に押せば、問題なく動作します。おそらく、DataGridViewに表の表示が終わった直後のタイミングで(1)を呼び出せばうまく動くものと思いますが、表示が終わったことを何で知ればよいのか、その方法が分かりません。

    発生する例外は、「KeyNotFoundExceptionはユーザーコードによってハンドルされませんでした」、場所は、DataGridView.cs の

      private FrameworkElement GetGridCell(DataGridViewCell cell)
      {
      ↓ここ
       var element =
    this.grid.Columns[cell.ColumnIndex].GetCellContent(this.rowContainer[cell.RowIndex]);
       while (true)
       {
        if (element == null)
         return null;

        if (element is DataGridCell)
         return element;

        element = element.Parent as FrameworkElement;
       }
      }

    です。

    2011年9月28日 8:49
  • ソースコード(DataGridView, DataTable)は知り合いから譲ってもらったものです。ただし、今回の例だけではなく、たとえば、SQL Serverなどのデータベースへ問い合わせるようなプログラムを作成していて、データを読み込んで表示が終わったタイミングで、「データを読み込みました」などのメッセージを表示させたい場合にも、同じことが言えます。

    2011年9月28日 8:55
  • こんにちは。
    そのDataGridView.csの実装がどうなっているかわからないのでこのケースに当てはまるかはわかりませんが
    一般的なDataGridのお話として言えることは

    DataGridRowは実際に描画される時までインスタンスは作られない
    (AutoGenerateColumnsをTrueにしている場合は自動生成Columnも。)

    ということです。

    質問文のやりかただとすると、
    あるはずの行や列が見つからなくてエラーになっているような気がしますので、

    dataGridView1.DataSource = dt;

    の後に

    DataGrid.UpdateLayout();
    


    を入れてあげるといけるんじゃないかと思います。
    (DataGridView.csがUpdateLayoutメソッドをサポートしているかどうかはわかりませんが)
    2011年10月2日 13:00
  • Uchidaさん、どうもありがとうございます。

    早速試してみましたら、その方法で解決いたしました!!

    ただ1つだけ気になったのは、

    DataTable dt;
    dt = new DataTable(strs);
    dataGridView1.DataSource = dt;
    dataGridView1.UpdateLayout();
    Button2_Click(sender, e);

    はうまく動いたのですが、

    DataTable dt;
    dt = new DataTable(strs);
    dataGridView1.DataSource = dt;
    dataGridView1.UpdateLayout();
    MessageBox.Show("TEST");

    とした場合、テーブルが表示される前に、"TEST"ダイアログが先に表示されてしまいます。

    それの理由が良く分からないのですが、でも当初の目的は達成できましたので、これで解決といたします。

    ありがとうございました。大変助かりました。m(__)m

    2011年10月3日 1:10