2012年12月3日月曜日

DataGridの行ヘッダに行番号を表示

CSVファイルを読み込み、行ヘッダに行番号がある DataGrid に表示します。
CSVファイルは、GetCsvListList メソッドで List<List<string>> に格納し、GetCsvDataTable メソッドで、DataTable に入れ直しています。DataTableに入れ直すときに、最初の列に "Index"列を追加して、行番号を格納します。
DataGridは、AutoGenerateColumnsプロパティを true にしています。よって、そのままバインドすると、"Index"列が最初の列に表示されてしまうので、AutoGeneratingColumn イベントで、"Index"列の生成をキャンセルしています。

private void dataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    if (e.PropertyName == "Index")
    {
        e.Cancel = true;
    }
}

行番号は、DataGrid の RowHeaderStyle でバインドさせます。DataRow の最初の要素が"Index"列なので、Binding Path=[0] と指定します。

<Style TargetType="{x:Type DataGridRowHeader}">
    <Setter Property="Content" Value="{Binding Path=[0]}" />
</Style>




MainWindow.xaml

<Window x:Class="DataGridTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Height="300" Width="400">
    <Window.CommandBindings>
        <CommandBinding Command="Open" Executed="OpenCommandHandler"/>
    </Window.CommandBindings>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Menu Grid.Row="0">
            <MenuItem Command="Open" />
        </Menu>
        <DataGrid Grid.Row="1" Name="dataGrid" AutoGeneratingColumn="dataGrid_AutoGeneratingColumn"
                  CanUserAddRows="False" CanUserDeleteRows="False" >
            <DataGrid.RowHeaderStyle>
                <Style TargetType="{x:Type DataGridRowHeader}">
                    <Setter Property="Content" Value="{Binding Path=[0]}" />
                </Style>
            </DataGrid.RowHeaderStyle>
        </DataGrid>
    </Grid>
</Window>


MainWindow.xaml.cs

using Microsoft.Win32;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;

namespace DataGridTest
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void OpenCommandHandler(object sender, ExecutedRoutedEventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            if (ofd.ShowDialog() == true)
            {
                string content = File.ReadAllText(ofd.FileName, Encoding.GetEncoding("Shift_JIS"));
                DataTable dt = GetCsvDataTable(content);
                this.dataGrid.ItemsSource = dt.DefaultView;
            }
        }

        private void dataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
        {
            if (e.PropertyName == "Index")
            {
                e.Cancel = true;
            }
        }

        private static DataTable GetCsvDataTable(string content)
        {
            List<List<string>> lists = GetCsvListList(content);

            DataTable dt = new DataTable();
            dt.Columns.Add("Index");
            for (int i = 0; i < lists[0].Count; i++)
            {
                dt.Columns.Add();
            }
            for (int rowIndex = 0; rowIndex < lists.Count; rowIndex++)
            {
                List<string> list = lists[rowIndex];
                DataRow dr = dt.NewRow();
                dr[0] = rowIndex + 1;
                for (int columnIndex = 0; columnIndex < list.Count; columnIndex++)
                {
                    dr[columnIndex + 1] = list[columnIndex];
                }
                dt.Rows.Add(dr);
            }
            return dt;
        }

        private static List<List<string>> GetCsvListList(string content)
        {
            List<List<string>> lists = new List<List<string>>();
            List<string> lastList = new List<string>();
            lists.Add(lastList);
            lastList.Add("");
            Regex regex = new Regex(",|\\r?\\n|[^,\"\\r\\n][^,\\r\\n]*|\"(?:[^\"]|\"\")*\"");
            MatchCollection mc = regex.Matches(Regex.Replace(content, "\\r?\\n$"""));
            foreach (Match in mc)
            {
                if (m.Value == ",")
                {
                    lastList.Add("");
                }
                else if (m.Value == "\n" || m.Value == "\r\n")
                {
                    lastList = new List<string>();
                    lists.Add(lastList);
                    lastList.Add("");
                }
                else
                {
                    lastList[lastList.Count - 1] = m.Value.StartsWith("\"") ?
                        m.Value.Substring(1, m.Value.Length - 2).Replace("\"\"""\"") : m.Value;
                }
            }
            return lists;
        }
    }
}

0 件のコメント:

コメントを投稿