QA@IT

VisualBasicのDataGridでカラム名にピリオドが含まれる時の動き

2994 PV

質問の投稿は初めてですので、失礼などありましたらお許しください。

VisualBasicで、DataGrid上にデータを表示しようとすると、タイトルにピリオド"."が入ったときだけDataGrid上にデータが表示されなくなります。
操作の手順とプログラムコードは以下の通りです。例えば以下のコードで、ColumnNameを"Test"として実行しボタンクリックすると、"abc"が表示されますが、"Test.1"などカラム名にピリオドを入れると、"abc"が表示されなくなります。
解決方法をご存知の方がいらっしゃいましたら教えて頂けると助かります。

  1. VisualStudio2010(言語はVisualBasic)で、WPFアプリケーション形式の新規プロジェクトを作成する。(名前をWpfApplication1とします)
  2. ソリューションエクスプローラで"WpfApplication1"を右クリック>追加で、データセットを一つ追加する。(名前はデフォルトのDataSet1.xsdとします)
  3. ソリューションエクスプローラで"DataSet1.xsd"をダブルクリックし、表示された作業ウィンドウ上で右クリック>追加>DataTableで、DataTableを一つ追加する。(名前は特に変更せずDataTable1のままとします)
  4. ソリューションエクスプローラのMainWindow.xamlをダブルクリックし、左に表示されたデータソースタブからDataTable1をフォーム上にドラッグする。(形式はDataGridとします)
  5. フォーム上にコマンドボタンを1つ追加し、clickイベントハンドラに以下のコードを追加する。
    Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
        Dim DataSet As WpfApplication1.DataSet1
        Dim DataTable As System.Data.DataTable
        Dim ColumnName As String = New String("Test")       ' abcが表示される
        'Dim ColumnName As String = New String("Test.1")    ' abcが表示されない

        DataSet = CType(Me.FindResource("DataSet1"), WpfApplication1.DataSet1)
        DataTable = CType(DataSet.Tables("DataTable1"), System.Data.DataTable)

        DataTable.Clear()
        DataTable1DataGrid.AutoGenerateColumns = True

        DataTable.Columns.Add(ColumnName)

        DataTable.Rows.Add()
        DataTable.Rows(DataTable.Rows.Count - 1).Item(DataTable.Columns.IndexOf(ColumnName)) = "abc"
    End Sub

回答

こんにちは、たしかにWPFのデータグリッドにおいて列名にピリオド(ドット)が含まれると表示されませんね。
私のVS2010でも再現しました。

原因としては、名前がXPATHとして評価されるため、XPATHで意味のある記号が含まれると困ったことになる、という具合の様です。同様にスラッシュ(/)を使った場合も同じようにabcが表示されませんでした。

対応策ですが、

  • 他の記号を用いる
    アンダースコア(_)を利用する分には問題ないようですので使える記号を利用するという手があるようです。

  • ユニコードキャラクタで置換する
    見た目重視の場合です。
    たとえば提示されたコードを以下のようにします。

    Dim ColumnName As String = New String("Test.1")
    ColumnName = ColumnName.Replace("."c, ChrW(&H2024)) 
    

    スラッシュも併せて置換する場合は

    Dim ColumnName As String = New String("Test/.1")
    ColumnName = ColumnName.Replace("."c, ChrW(&H2024)).Replace("/"c, ChrW(&H2044)) 
    

    となります。
    またこれは以下のように簡略することもできます(これは余談です)

    Dim ColumnName = "Test/.1".Replace("."c, ChrW(&H2024)).Replace("/"c, ChrW(&H2044)) 
    

    この様にすれば一応見た目はピリオドのまま abcも表示させることができますが、
    問題があります。

    "Test.1""Test.1".Replace("."c, ChrW(&H2024))は同一ではないということです
    つまり

    IF "Test.1" = "Test.1".Replace("."c, ChrW(&H2024)) Then
    ' 同一ではないのでここに入ることはありません。
    End IF
    

    ということです。比較の前にそろえてあげる必要が出てきます。

他にも解決策があるかもしれませんが、私が見つけたのは上記の2つでした。

編集 履歴 (3)

ご回答ありがとうございました。
原因と思われる内容まで説明いただき、非常に参考になりました。

私の場合、カラム名は表示のみに使用し処理に使うことはないということと、プログラム側の都合でピリオドを使用禁止にしたくないという理由から、ユニコードキャラクタで置換する方法を選択しました。
現在は問題なく動作しています。

ただ、どういうわけかVisualStudioの2010と2012が共存している環境(おそらくVS2012のみインストールされている場合でも同じだと思いますが)では、ピリオドが入っているかどうかに関わらず、カラム名すら表示されませんでした。同じソースをVS2010と2012いずれでコンパイルした場合でも同じで、さらにVS2012で一からプロジェクトを作り直しても同じでした。
原因はまだ調べていませんが、将来的に開発環境をアップグレードする際には、注意する必要がありそうです。

編集 履歴 (0)
  • 最後に DataTable1DataGrid.DataContext = DataTable とすれば表示はされますが、バインドしなおしてるしこれで正しいのかは私もわかっていません。動きが違うのもなんででしょうねぇ。4.5で何か変わったのかな。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。