DataGridを操作しようとするとインデックスエラーになる


事象

WPFアプリで、WindowにDataGridを設置した。Windowの初期化時に、DataGridの列のプロパティを操作しようとするとエラーが出た。

エラー内容

System.ArgumentOutOfRangeException
インデックスが範囲を超えています。負でない値で、コレクションのサイズよりも小さくなければなりません。
パラメーター名:index

詳細

表示したかったのはこちらの画面。DataGridが一覧表になっており、保存や削除のボタンがある。

xamlはこちら。

Terminals.xaml
<Window x:Name="端末登録" x:Class="SkillAttacher.Admin.Terminals"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="端末登録" Height="700" Width="600" ResizeMode="NoResize" WindowStartupLocation="CenterScreen" Icon="/SkillAttacher;component/rect3063.ico">
    <WrapPanel>
        <StackPanel>
            <Label x:Name="Error" Content="" Margin="30,20,0,0" Foreground="Red"></Label>
            <DataGrid x:Name="GridTerminals" HorizontalAlignment="Left" Margin="30,10,0,0" VerticalAlignment="Top" Height="570" Width="400" RenderTransformOrigin="0.5,0.5" 
              SelectionMode="Single" SelectionUnit="CellOrRowHeader" CanUserResizeColumns="False" CanUserReorderColumns="False" CanUserResizeRows="False" CanUserDeleteRows="False"
              RowEditEnding="DataGrid_Edit" AddingNewItem="DataGrid_Edit" CanUserSortColumns="False">
                <DataGrid.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform/>
                        <TranslateTransform/>
                    </TransformGroup>
                </DataGrid.RenderTransform>
            </DataGrid>
        </StackPanel>
        <StackPanel>
            <Button x:Name="Regist" Content="保存" HorizontalAlignment="Left" Height="65" Margin="30,395,0,0" VerticalAlignment="Top" Width="100" Click="Regist_Click"/>
            <Button x:Name="Delete" Content="削除" HorizontalAlignment="Left" Height="65" Margin="30,20,0,0" VerticalAlignment="Top" Width="100" Click="Delete_Click"/>
            <Button x:Name="Back" Content="戻る" HorizontalAlignment="Left" Height="45" Margin="30,40,0,0" VerticalAlignment="Top" Width="100" Click="Back_Click"/>
        </StackPanel>
    </WrapPanel>
</Window>

xaml.csはこちら(抜粋)。コンストラクタから呼び出したメソッドの中で、DataGridのColmunを操作する箇所でエラーが発生した。

Terminals.xaml.cs

/// <summary>
/// コンストラクタ
/// </summary>
public Terminals()
{
    InitializeComponent();
    SetData();
}

/// <summary>
/// データグリッドにデータをバインド
/// </summary>
private void SetData()
{
    var ds = new DataSet();
    try
    {
        conn = new SqlConnection(Define.CONN_STR);
        conn.Open();
        string qry = "SELECT * FROM Terminals WHERE IsDelete='False' ORDER BY TerminalDisplayOrder ASC;";
        adapter = new SqlDataAdapter(qry, conn);
        adapter.SelectCommand.CommandType = CommandType.Text;
        adapter.Fill(ds);
    }
    catch (Exception ex)
    {
        // 省略
    }
    GridTerminals.ItemsSource = ds.Tables[0].DefaultView;
    GridTerminals.Columns[0].Width = 150;
    GridTerminals.Columns[1].Width = 210;
    GridTerminals.Columns[0].Header = HEADER_TERMINAL_CD;
    GridTerminals.Columns[1].Header = HEADER_TERMINAL_IP_ADDRESS;
}

データをDBから取得して、バインドしており、DataGridのItemsには数件のデータが入っている。しかしDataGridのColumns.Countは0になっている。
列数が0なのに第一列目を装飾しようとしたため、落ちてしまっていた。

解決方法


/// <summary>
/// コンストラクタ
/// </summary>
public Terminals()
{
    InitializeComponent();
    //SetData();
    ContentRendered += (s, e) => SetData();
}

画面がレンダリングされる前にDataGridの列を操作しようとしたことが原因。
ContentRenderdのイベントに問題のメソッドを追加し、レンダリング後に行うようにしたら、ちゃんと動いた。