C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

datagridviewからxmlへの出力について /kaz (18/04/10(Tue) 07:45) #87059
Re[1]: datagridviewからxmlへの出力について /FAQ U (18/04/10(Tue) 10:08) #87060
│└ Re[2]: datagridviewからxmlへの出力について /kaz (18/04/10(Tue) 11:01) #87061
Re[1]: datagridviewからxmlへの出力について /魔界の仮面弁士 (18/04/10(Tue) 11:35) #87063
│└ Re[2]: datagridviewからxmlへの出力について /魔界の仮面弁士 (18/04/10(Tue) 12:27) #87064
Re[1]: datagridviewからxmlへの出力について /WebSurfer (18/04/10(Tue) 14:21) #87068
│├ Re[2]: datagridviewからxmlへの出力について /kaz (18/04/10(Tue) 15:02) #87070
││├ Re[3]: datagridviewからxmlへの出力について /魔界の仮面弁士 (18/04/10(Tue) 15:39) #87074
││└ Re[3]: datagridviewからxmlへの出力について /WebSurfer (18/04/10(Tue) 17:18) #87075
│└ Re[2]: datagridviewからxmlへの出力について /kaz (18/04/10(Tue) 14:47) #87069
│  └ Re[3]: datagridviewからxmlへの出力について /魔界の仮面弁士 (18/04/10(Tue) 15:11) #87073
Re[1]: datagridviewからxmlへの出力について /WebSurfer (18/04/11(Wed) 12:58) #87091
  └ Re[2]: datagridviewからxmlへの出力について /kaz (18/04/11(Wed) 22:09) #87102
    ├ Re[3]: datagridviewからxmlへの出力について /WebSurfer (18/04/11(Wed) 22:38) #87104
    │└ Re[4]: datagridviewからxmlへの出力について /kaz (18/04/11(Wed) 23:36) #87106
    │  └ Re[5]: datagridviewからxmlへの出力について /WebSurfer (18/04/12(Thu) 12:11) #87114
    └ Re[3]: datagridviewからxmlへの出力について /WebSurfer (18/04/11(Wed) 22:50) #87105
      └ Re[4]: datagridviewからxmlへの出力について /kaz (18/04/11(Wed) 23:52) #87107
        ├ Re[5]: datagridviewからxmlへの出力について /魔界の仮面弁士 (18/04/12(Thu) 01:05) #87108
        │└ Re[6]: datagridviewからxmlへの出力について /kaz (18/04/12(Thu) 02:47) #87110 解決済み
        └ Re[5]: datagridviewからxmlへの出力について /WebSurfer (18/04/12(Thu) 12:23) #87115 解決済み


親記事 / ▼[ 87060 ] ▼[ 87063 ] ▼[ 87068 ] ▼[ 87091 ]
■87059 / 親階層)  datagridviewからxmlへの出力について
□投稿者/ kaz (1回)-(2018/04/10(Tue) 07:45:46)

分類:[C#] 

開発環境:visualstudio2017/C#.net4.6/フォームアプリ

datagridviewの内容をwritexmlでxmlファイルに書き出すときに
datagridviewで空白のセルがxmlファイル中に書き出されず困っています。
要点を整理するために2つに分けて質問します

【質問1】
例えば、
| りんご | 50 |
を出力すると

<fruits>
<name>りんご</name>
<price>50</price>
</fruits>
となるのが、

| りんご |   |
の場合は(価格が空白)、
<fruits>
<name>りんご</name>
</fruits>

と<price>の項目が消えてしまいます
<price></price>
とセルが未記入の項目を”空文字”等で出力する方法は無いでしょうか?

【質問2】
datagridviewにチェックボックスが配置されていて
チェックをつけたセルについては、
<checked>true</checked>
と出力されるのですが
チェックがついていないセルについては
【質問1】の状況と似たように
項目自体が出力されません
未チェックの項目を
<checked>false</checked>
と出力するにはどうしたら良いでしょうか?


以上2点、アドバイスいただければ幸いです
足りない情報があれば追加します
また、参考になるウェブサイトを紹介していただく場合、英語のサイトでも問題ございません
よろしくおねがいします

[ □ Tree ] 返信 編集キー/

▲[ 87059 ] / ▼[ 87061 ]
■87060 / 1階層)  Re[1]: datagridviewからxmlへの出力について
□投稿者/ FAQ U (1回)-(2018/04/10(Tue) 10:08:27)
XML出力はどの方法で行っていますか?
[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87060 ] / 返信無し
■87061 / 2階層)  Re[2]: datagridviewからxmlへの出力について
□投稿者/ kaz (3回)-(2018/04/10(Tue) 11:01:32)
No87060 (FAQ U さん) に返信
> XML出力はどの方法で行っていますか?

返信有難うございます

xml書き込みは、
DataSet.WriteXml メソッド (String,&#8194;XmlWriteMode)で
xmlwritemodeをWriteSchemaにして行っています

ソースコード的には
【読み込み&datagridviewへの表示】
 mydataset.ReadXml(filepath);
dataGridView1.DataSource = mydataset;
dataGridView1.DataMember = "label";

【書き込み】
mydataset.WriteXml(filepath,XmlWriteMode.WriteSchema)

こんな感じになります


[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87059 ] / ▼[ 87064 ]
■87063 / 1階層)  Re[1]: datagridviewからxmlへの出力について
□投稿者/ 魔界の仮面弁士 (1633回)-(2018/04/10(Tue) 11:35:40)
C# をお使いなのですし、質問文中でも大文字小文字を
正しく書き分けるようにした方が良いかと思います。
(これが VB の質問なら、大文字小文字の違いにも目を瞑るのですが)


No87059 (kaz さん) に返信
> | りんご |   |
> の場合は(価格が空白)、
> <fruits>
> <name>りんご</name>
> </fruits>
> と<price>の項目が消えてしまいます

price フィールドのデータ型は何ですか?
また、「空白」の場合にはどのような値がセットされていますか?



No87061 (kaz さん) に返信
> xml書き込みは、
> DataSet.WriteXml メソッド (String, XmlWriteMode)で
> xmlwritemodeをWriteSchemaにして行っています

質問文と内容が微妙に異なっているようですね。

現在のコードは、「DataGridView からの XML 出力」ではなく、
「DataSet からの XML 出力」になってしまっているように見えますが、
それで構わないのでしょうか?

たとえば、DataTable の列の中に「DataGridView にバインドしていない列」があった場合や、
DataGridView の列の中に「データバインドしていない列」が含まれていると、
DataSet.WriteXml の結果は、DataGridView とは合致しませんよね。


> dataGridView1.DataSource = mydataset;
> dataGridView1.DataMember = "label";
あれ? 出力される XML は、<fruits> なのに、
DataMember に指定するテーブル名は "label" なのですか??


まず【質問1】の方ですが、
mydataset.Tables["label"] や
mydataset.Tables["fruits"] の列定義などに
特に制限が無いのであれば、たとえば下記のコードで

<fruits>
 <name>りんご</name>
 <price />
</fruits>

な構造を出力されます。


var mydataset = new DataSet("kaz");
var tbl = mydataset.Tables.Add("fruits");
tbl.Columns.Add(new DataColumn("name", typeof(string)) { AllowDBNull = false, ReadOnly = true });
tbl.Columns.Add(new DataColumn("price", typeof(string)) { AllowDBNull = false, ReadOnly = true });
tbl.Rows.Add("リンゴ", "50");
tbl.Rows.Add("りんご", string.Empty);
tbl.AcceptChanges();

dataGridView1.DataSource = mydataset;
dataGridView1.DataMember = "fruits";

var sb = new System.Text.StringBuilder();
using (var output = new System.IO.StringWriter(sb))
{
 mydataset.WriteXml(output, XmlWriteMode.WriteSchema);
}
textBox1.Text = sb.ToString();
[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87063 ] / 返信無し
■87064 / 2階層)  Re[2]: datagridviewからxmlへの出力について
□投稿者/ 魔界の仮面弁士 (1634回)-(2018/04/10(Tue) 12:27:08)
No87059 (kaz さん) に返信
> <price></price>
> とセルが未記入の項目を”空文字”等で出力する方法は無いでしょうか?

XmlWriteMode.WriteSchema を指定しているのですから、
XML 要素 <price> が出力されなかったとしても、
DataTable に price 列が存在することは自明です。

price 要素が出力されないことによって、何か弊害があるのでしょうか?
ReadXml の結果には影響を及ぼさないと思うのですが…。


ちなみに要素がない場合は DBNull 相当であることを表しますが、
<price/> や <price></price> の場合は空文字列を表します。


そのため price 列が、先の回答のように string 型のフィールドであれば
大丈夫ですが、列のスキーマがたとえば
 <xs:element name="price" type="xs:decimal" />
の場合(上記は decimal 型のフィールド)には、
<price/> や <price></price> の要素が含まれていると、
"" を decimal 型にパースできず、ReadXml メソッドで
読み込めなくなってしまうのでご注意ください。



どうしても空要素が必要なら、XSLT あるいは DOM 操作で書き加えるか、
そもそも WriteXml / ReadXml を使わず、XLinq 等で手動で読み書きするよう
方針を変えてみてはいかがでしょうか。



で、今度は【質問2】について。


> datagridviewにチェックボックスが配置されていて

この列は、バインド列ですか? それとも非バインド列ですか?

DataSet や DataView から辿る場合は、チェックボックス列にバインドさせるための
何らかのフィールド(通常は boolean 型)をテーブルに追加しておく必要があるでしょう。
boolean 以外の型を使う場合は、DataGridViewCheckBoxColumn に対して
TrueValue/IndeterminalValue プロパティを指定してやれば OK です。


DataGridView 側から辿る場合は、バインドはしてもしていなくても大丈夫です。
foreach 等で DataGridViewRow を列挙する際に、DataGridView の各行に対して
 object o = 行.Cells["チェックボックス列名"].Value;
で、チェック状態を判別できますし、そこから
 var rowView = (DataRowView)行.DataBoundItem;
 DataRow row = rowView.Row;
 // DataTable table = row.Table;
 // DataSet ds = table.DataSet;
などと逆に辿ることで、DataRow の内容にもアクセスできます。


> チェックがついていないセルについては
そのデータが DBNull になっているのではありませんか?

AllowDBNull = false にしておいて、新規行に対しては、
初期値として DataGridViewCheckBoxCell の TrueValue/FalseValue の
いずれかを渡すようにすれば良いのではないでしょうか。
[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87059 ] / ▼[ 87070 ] ▼[ 87069 ]
■87068 / 1階層)  Re[1]: datagridviewからxmlへの出力について
□投稿者/ WebSurfer (1462回)-(2018/04/10(Tue) 14:21:05)
No87059 (kaz さん) に返信

表題は「datagridviewからxmlへの出力について」となっていますが、実際は DataGridView 上のデータを
直接 xml 形式にするわけではなく、DataSet / DataTable が DataGridView にデータバインドされていて、
ユーザーが DataGridView を編集した結果を DataSet / DataTable に反映し、その DataSet / DataTable
の内容を xml ファイルに書き出すという話なのですか?

で、問題は DataSet / DataTable のある列・行にデータがない(null? String.Empty? DBNull.Value? 何
になるのでしょう)とき、その項目が xml ファイルに書き出されないということですか?
[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87068 ] / ▼[ 87074 ] ▼[ 87075 ]
■87070 / 2階層)  Re[2]: datagridviewからxmlへの出力について
□投稿者/ kaz (5回)-(2018/04/10(Tue) 15:02:16)
No87068 (WebSurfer さん) に返信

> DataSet / DataTable が DataGridView にデータバインドされていて、
> ユーザーが DataGridView を編集した結果を DataSet / DataTable に反映し、その DataSet / DataTable
> の内容を xml ファイルに書き出す

まさにその通りです
ただ、手作業でDataGridViewを編集した場合は、同時にDataSet/DataTableの方に反映されますが
プログラムでDataGridViewを編集した場合はDataSetに反映されないようなので
プログラムから直接DataSet/DataTableを編集する事もあります

> で、問題は DataSet / DataTable のある列・行にデータがない(null? String.Empty? DBNull.Value? 何
> になるのでしょう)とき、その項目が xml ファイルに書き出されないということですか?

これもまさにその通りです
空白(データない)という状態がプログラム的にどういう事なのか
DBNullを今日はじめて知った自分には、よく理解できていないので勉強します
[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87070 ] / 返信無し
■87074 / 3階層)  Re[3]: datagridviewからxmlへの出力について
□投稿者/ 魔界の仮面弁士 (1637回)-(2018/04/10(Tue) 15:39:15)
No87070 (kaz さん) に返信
> プログラムでDataGridViewを編集した場合はDataSetに反映されないようなので
> プログラムから直接DataSet/DataTableを編集する事もあります

バインドしている場合は、データソース(DataTable 等)を直接編集した方が良いです。
あるいは先に紹介した方法で、DataGridViewRow 側から
バインド元の DataRow を辿って書き換えるのが確実です。

コードから DataGridView 側を編集した場合は、EndEdit メソッドを呼び出して
値を確定させる必要があります。ただ、処理によっては
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=35999&forum=7
のような手間がかかることもあるので、自分の場合は BindingSource を
経由させるようにしています。この方が状態管理が楽なので。


DataGridView 側から入力したデータの状態については、
ざっくり分けて下記の 3 段階があります。
ここで紹介していない状態も幾つかあるのですが、今回は省略。

(1) DataGridView 上でセル値が編集されたが、まだ確定していない状態
(2) セル値が入力されたが、編集中の行が未確定の状態
(3) セル値が入力されたが、編集中の行が確定した状態


1 は、DataGridView の左端が、ペンアイコンになっている状態
この状態では、入力値はまだ DataGridView 上で管理されているだけであり、
DataRow には渡されていません。

2 はたとえば、DataGridView の新規行にデータを入力して、
そのまま同じ行の別のセルに移動した時の状態。
入力したデータは DataRow にも渡されていますが、
その DataRow はまだ DataTable に割り当てられていません。(Detached)

3 は、DataGridView で入力後に、他の行に移動した場合など。
DataRow の内容は DataTable 側にも格納された状態となります。
[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87070 ] / 返信無し
■87075 / 3階層)  Re[3]: datagridviewからxmlへの出力について
□投稿者/ WebSurfer (1463回)-(2018/04/10(Tue) 17:18:10)
No87070 (kaz さん) に返信

>>で、問題は DataSet / DataTable のある列・行にデータがない(null? String.Empty? DBNull.Value? 何
>>になるのでしょう)とき、その項目が xml ファイルに書き出されないということですか?
>
> これもまさにその通りです
> 空白(データない)という状態がプログラム的にどういう事なのか
> DBNullを今日はじめて知った自分には、よく理解できていないので勉強します

自分でアプリを作って検証してみましたが、DataGridView 上に表示された文字列を削除すると DataTable の
当該列・行には DBNull.Value が入るようです。

で、そのまま WriteXml で書き込むと、質問者さんが言われるように、xml ファイル上では当該項目は消えて
しまうのを確認できました。

消えないようにするには、DBNull.Value に代えて String.Empty を DataTable の当該列・行に代入してから
WriteXml で書き込むとよさそうです。

お試しください。
[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87068 ] / ▼[ 87073 ]
■87069 / 2階層)  Re[2]: datagridviewからxmlへの出力について
□投稿者/ kaz (4回)-(2018/04/10(Tue) 14:47:50)
No87063 (魔界の仮面弁士 さん) に返信
質問内容について、しっかり整理出来てない所が多々あり
申し訳ありません
大文字小文字は気を付けるようにします
また、質問文内の例については
即興で手書きしたため整合性が取れていない所がありました
すいません


> priceフィールドのデータ型は何ですか?
> また、「空白」の場合にはどのような値がセットされていますか?
例ではintのつもりで適当に書きましたが
実際には
<xs:element name="Name" type="xs:string" minOccurs="0" />
<xs:element name="IsEnabled" type="xs:boolean" minOccurs="0" />
(↓がチェックボックスに対応)
というようなxmlを読み込んで表示しているので
扱う型はstringやbooleanになるかと思います
(しかも、今扱っているデータに数字列はないので例としては大変不適切でした
nullや空文字が許容されているか型か?は、今回の話にとても大切ですね)

また、「空白」セルをGetType()してみた所
ご指摘の通りDBNullが入っていました
対応するDataSetの要素も同様でした
(恥ずかしながらDBNullをいう存在を初めて知りました)

今回【質問1】に至った経緯は
xmlを手書きで編集する際に、全要素のひな形が予め存在していたほうが
編集しやすいと思ったからです
xmlを手書き編集する事自体横着だとは思いますが
自分で作り、自分だけが使う予定のプログラムなので大目に見ていただければ・・

DataSetとDataGridViewどちらからの出力かという事に関しては
WebSurferさんへの返信にまとめさせていただきます

ご指摘にあるようにバインドしていない列が存在する場合の挙動を
よく理解していないこともあって
現状は、DataSet全列をDataGrieViewに作り
いらない列は非表示にして対応しています

> この列は、バインド列ですか? それとも非バインド列ですか?
”バインドする”というのが
VSのデザイナーでDataGridViewの「列の編集」から列を追加し
xmlに対応させたDataPropertyNameを設定するという事ならば
全列バインドしていると思います


自分の拙い質問に対してかなり先回りしてご回答頂いたので
これから、アドバイスを参考に試行錯誤してみたいと思います
一旦解決マークはつけずに、また結果を報告します
返信ありがとうございました
[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87069 ] / 返信無し
■87073 / 3階層)  Re[3]: datagridviewからxmlへの出力について
□投稿者/ 魔界の仮面弁士 (1636回)-(2018/04/10(Tue) 15:11:33)
No87069 (kaz さん) に返信
> xmlを手書きで編集する際に、全要素のひな形が予め存在していたほうが
> 編集しやすいと思ったからです

Visual Studio で、プロジェクトに DataSet をあらかじめ含めておくと、
テーブル名や列名をあらかじめ定めた、「型付 DataSet」が作れます。

この場合、DataSet ファイル(*.xsd)自体にスキーマ情報が含まれていますので、
WriteSchema を使う必要が無く、データ部のみの XML でやりとりできます。

> xmlを手書き編集する事自体横着だとは思いますが
> 自分で作り、自分だけが使う予定のプログラムなので大目に見ていただければ・・
手書きにも対応させたいのであれば、データ部のみの XML にした方が楽かと思います。


> 現状は、DataSet全列をDataGrieViewに作り
> いらない列は非表示にして対応しています
わざわざ非表示列を作らずとも、
先に述べた DataBoundItem プロパティを使うことで、
DataSet 側の該当行の全ての列データにアクセスできます。
[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87059 ] / ▼[ 87102 ]
■87091 / 1階層)  Re[1]: datagridviewからxmlへの出力について
□投稿者/ WebSurfer (1465回)-(2018/04/11(Wed) 12:58:41)
No87059 (kaz さん) に返信

<追伸>

> 【質問2】
> datagridviewにチェックボックスが配置されていて
> チェックをつけたセルについては、
> <checked>true</checked>
> と出力されるのですが
> チェックがついていないセルについては
> 【質問1】の状況と似たように
> 項目自体が出力されません

こちらは自分が試した限りでは再現できませんでした。

DataGridView 上でのチェックボックスのチェックの有無と xml ファイルの true / false は
きちんと期待通りに対応します。

どのように試したかと言うと、以下の通りです。質問者さんのケースとどこが違うかチェック
してみてください。

(1) SQL Server の Microsoft のサンプルデータベースの Northwind の Products テーブルか
  ら以下のクエリを使ってインラインスキーマ付きの xml を生成。
use NORTHWIND
go
select top 5 * from Products FOR XML raw('product'),
   root('root'), elements, XMLSCHEMA('MyURI')

	UserInfo.xml という名
  前を付けて xml ファイルとして保存。

(2) Visual Studio で Windows Forms アプリのプロジェクトを作成。それに、上記 (1) の手順
  で作った xml を UserInfo.xml という名前を付けて保存。

(3) Windows Forms アプリに以下のクラスファイル(ビジネスロジック)を追加。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;

namespace EditXmlFileOnDataGridView
{
    public class UserInfoTable : IDisposable
    {
        const string filePath = @"C:\Users\...\UserInfo.xml";
        private DataSet myDataSet;

        public UserInfoTable()
        {
            myDataSet = new DataSet();
            myDataSet.Locale = System.Globalization.CultureInfo.InvariantCulture;
            myDataSet.ReadXml(filePath, XmlReadMode.ReadSchema);
        }

        public virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                myDataSet.Dispose();
            }
        }

        public void Dispose()
        {
            Dispose(true);
            System.GC.SuppressFinalize(this);
        }

        ~UserInfoTable()
        {
            Dispose(false);
        }

        public DataSet GetDataSet()
        {
            return myDataSet;
        }

        // ・・・中略・・・

        public void Save()
        {
            myDataSet.WriteXml(filePath, XmlWriteMode.WriteSchema);
        }
    }
}

(4) 自動生成されている Form1 にデザイン画面で DataGridView, Button を貼り付け。
  以下のコードを書く。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace EditXmlFileOnDataGridView
{
    public partial class Form1 : Form
    {
        private BindingSource bindingSource1 = new BindingSource();
        private UserInfoTable userInfo;

        public Form1()
        {
            InitializeComponent();
            this.userInfo = new UserInfoTable();
            DataTable table = userInfo.GetDataSet().Tables[0];
            table.AcceptChanges();
            this.bindingSource1.DataSource = table;
            this.dataGridView1.DataSource = bindingSource1;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.bindingSource1.EndEdit();
            this.userInfo.Save();
            this.userInfo.GetDataSet().Tables[0].AcceptChanges();
        }
    }
}

[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87091 ] / ▼[ 87104 ] ▼[ 87105 ]
■87102 / 2階層)  Re[2]: datagridviewからxmlへの出力について
□投稿者/ kaz (6回)-(2018/04/11(Wed) 22:09:05)
その後、色々試してみて
まだ部分的に切り出した実験コードレベルですが
質問で意図した動作はほぼ達成出来たと思われます

・型付データセットを作成
・必要な列を追加
・DefaultValueをString列はString.Empty、Boolean列はfalseに設定・・・(※1)
・スキーマを含めずWriteXmlで書き出す前に以下のようにDBNullを空文字やfalseに置換・・・(※2)


            for (int i = 0; i <= ds.Tables[0].Columns.Count - 1; i++)
            {
                for (int j = 0; j <= ds.Tables[0].Rows.Count - 1; j++)
                {
                    if (ds.Tables[0].Columns[i].DataType.ToString() == "System.String")
                    {
                        if (ds.Tables[0].Rows[j][i] == DBNull.Value)
                        {
                            ds.Tables[0].Rows[j][i] = String.Empty;
                        }
                    }

                    if (ds.Tables[0].Columns[i].DataType.ToString() == "System.Boolean")
                    {
                        if (ds.Tables[0].Rows[j][i] == DBNull.Value)
                        {
                            ds.Tables[0].Rows[j][i] = false;
                        }
                    }
                }
            }



この手順で、
読み込むxmlに抜けた要素がある場合も
DataGridViewを手書き/コードから編集、あるいは新規行を追加した場合も
目的の動作になることを確認しました

動作自体はうまくいったのですが
少々疑問に思う所もありまして

※1は、コード中で以下のように初期値を設定しているのですが
ds.Tables[0].Columns["Name"].DefaultValue = String.Empty;

同じことを型付データセットを作るデザイナーのプロパティから
設定する方法はあるのでしょうか?
String.Empty,、<String.Empty>など試してみましたが
空文字にならず、そのままString.Emptyや<String.Empty>という文字列がDataGridViewに表示されてしまいました
コードから設定すれば済む事ですが、気になったので

※2は、
列の型判定についてです
最初、以下のコードで型判定できると思ったのですが
if (ds.Tables[0].Columns[i].DataType is System.String)

VisualStudioのエディターで緑波線がついて
「式は指定された型’string’ではありません」
とあり、実際に正しく判定されませんでした
それで、ToString()でキャストした後、文字列として判定する方法に変更した所うまくいきました
最初のコードがダメな理由がわかりません



■No87091 (WebSurfer さん) に返信
> (1) SQL Server の Microsoft のサンプルデータベースの Northwind の Products テーブルか
>   ら以下のクエリを使ってインラインスキーマ付きの xml を生成。

すいません、この手順がわからないのですが
これはVisualStudioで行う操作なのでしょうか?
SQLは全く触ったことが無いもので・・・

[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87102 ] / ▼[ 87106 ]
■87104 / 3階層)  Re[3]: datagridviewからxmlへの出力について
□投稿者/ WebSurfer (1466回)-(2018/04/11(Wed) 22:38:33)
No87102 (kaz さん) に返信

> すいません、この手順がわからないのですが
> これはVisualStudioで行う操作なのでしょうか?

自分は SQL Server Management Studio を使いました。

でも、ポイントはそこではなく、何で作ろうとスキーマと xml 本体がきちんとできていれば、上に書いたコード
だけでチェックボックスは表示され、チェックの有無で xml の当該項目が true / false に書き換わるというこ
とです。

質問者さんが No87102 に書いたような DBNull で判定して false を代入する操作は必要はないです。



[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87104 ] / ▼[ 87114 ]
■87106 / 4階層)  Re[4]: datagridviewからxmlへの出力について
□投稿者/ kaz (7回)-(2018/04/11(Wed) 23:36:01)
No87104 (WebSurfer さん) に返信
> でも、ポイントはそこではなく、何で作ろうとスキーマと xml 本体がきちんとできていれば、上に書いたコード
> だけでチェックボックスは表示され、チェックの有無で xml の当該項目が true / false に書き換わるというこ
> とです。
>
> 質問者さんが No87102 に書いたような DBNull で判定して false を代入する操作は必要はないです。

「元のxmlがきちんと出来ている」
この条件が大切だと思われます

状況を整理すると
xmlから読み込んだデータをDataGridViewに表示した際
チェックボックスが未チェックになるのは2パターンあって
【1】元のxmlで要素がfalseの時
【2】元のxmlで要素が存在しない(DBNull)の時

【1】であれば、当然書き出したxmlでも正しくfalseが存在する
【2】のときは、書き出したxmlでも要素が欠けた状態になる
というのが今の自分の理解です

WebSurfer さんにご提示頂いたやり方で
元のxmlファイルに欠けた要素がある(例えば、チェックボックスに対応する要素が存在せずDBNullである場合)でも
書き出したxmlファイルでは、その要素はfalseとして存在しますでしょうか?

自分が試した型付データセットを用いる方法だと
元のxmlファイル中で欠けている要素は、それが文字列だろうとチェックボックスに対応する列だろうと
書き出したxml中でも、要素が消えたままになります

つまり、DBNullに相当する要素をxmlに書き出す(または、読み込むタイミングでもいいですが)ときに
「その要素が属している列の型がStrringであれば空文字へ、Booleanであればfalseへ」の変換が必要であり
その変換を誰がどこで行うのかという問題だと思います
(ご提示頂いた方法だと、自動変換されるのかも?)

更に、
そもそも、欠けた要素の存在するxmlを元データとして認めるのかという問題があります
最初に欠けた要素が存在しないxmlデータからスタートして
追記する場合も、要素が欠ける事がないようにすれば(例えば、DefaultValueを適切に設定するとか)
そもそも条件【2】に遭遇する事が無くなりますね

[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87106 ] / 返信無し
■87114 / 5階層)  Re[5]: datagridviewからxmlへの出力について
□投稿者/ WebSurfer (1468回)-(2018/04/12(Thu) 12:11:49)
No87106 (kaz さん) に返信

すでに解決済みになってますが・・・

> 状況を整理すると
> xmlから読み込んだデータをDataGridViewに表示した際
> チェックボックスが未チェックになるのは2パターンあって
> 【1】元のxmlで要素がfalseの時
> 【2】元のxmlで要素が存在しない(DBNull)の時

ちょっと違うかと。

データベースでは列に NULL 可/不可というのを設定できます。NULL 可に設定されている場合 xml
上で NULL を表すのが既定では要素が存在しないということになるそうです。

NULL 値が含まれる列の既定動作
https://docs.microsoft.com/ja-jp/sql/relational-databases/xml/columns-that-contain-a-null-value-by-default

データベースである列の型が bit(DataGridView 上でチェックボックスになる)で NULL 可の場合、
true, false, NULL の 3 つの値を取ることができます。xml 上では既定では以下のようになるはず
です。

true: <checked>true</checked>
false: <checked>false</checked>
NULL: 要素は存在しない

> 【1】であれば、当然書き出したxmlでも正しくfalseが存在する
> 【2】のときは、書き出したxmlでも要素が欠けた状態になる

自分の環境で試した Products テーブルの Discontiued 列(データ型は bit で NULL 不可)の場合、
前者はその通りです。後者は違います(欠けることはなくて true / false いずれかになります)。

> WebSurfer さんにご提示頂いたやり方で
> 元のxmlファイルに欠けた要素がある(例えば、チェックボックスに対応する要素が存在せずDBNullである場合)でも
> 書き出したxmlファイルでは、その要素はfalseとして存在しますでしょうか?

上にも書きましたように、自分が試した Products テーブルの Discontiued 列は NULL 不可なので、
xml 上では必ず要素が存在します。

xml のスキーマで NULL 可を表すのが minOccurs="0" のようですので(ちょっと自信なし)、試しに、
Products テーブルの Discontiued 列(データ型は bit で NULL 不可)から生成したスキーマを以下の
ようにして、xml の Discontiued 要素を削除して試してみました。

<xs:element name="Discontinued" type="app1:bit" />
  ↓
<xs:element name="Discontinued" type="app1:bit" minOccurs="0" />

その xml ファイルから DataSet / DataTable を生成すると、DataTable 上の当該要素は DBNull.Value
になります。

DataSet / DataTable を DataGridView に表示すると当該要素(DBNull.Value の)は空のチェックボ
ックスになります。

チェックを入れて xml ファイルを更新すると <Discontinued>true</Discontinued> になります。

チェックを外して xml ファイルを更新すると <Discontinued>false</Discontinued> になります(要素
は先所されません)。

ご参考まで。
[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87102 ] / ▼[ 87107 ]
■87105 / 3階層)  Re[3]: datagridviewからxmlへの出力について
□投稿者/ WebSurfer (1467回)-(2018/04/11(Wed) 22:50:15)
No87102 (kaz さん) に返信

> SQLは全く触ったことが無いもので・・・

何故 xml をデータソースに使っているのか分かりませんが、できれば多分 Visual Studio 2017 と一緒に
インストールされているであろう SQL Server Local DB と Visual Studio のデータソース構成ウィザー
ドを使って定番の構成のアプリを作ってみてはいかがでしょう?

DB が SQL Server の場合ですが、以下のチュートリアル、

チュートリアル : データベースへのデータの保存 (単一テーブル)
https://msdn.microsoft.com/ja-jp/library/0f92s97z(v=vs.120).aspx

10 行でズバリ !! 非接続型のデータ アクセス (ADO.NET) (C#)
https://code.msdn.microsoft.com/windowsdesktop/10-ADONET-C-cbfe7688

・・・のように Visual Studio のデータソース構成ウィザードを利用して型付 DataSet + TableAdapter
を作って、それを利用してアプリを作ると、以下のページの図のような構造のアプリが、ほとんど自分で
コードを書くこと無しに作れます。

Windows フォーム アプリケーションでのデータへの接続
https://msdn.microsoft.com/ja-jp/library/wxt2cwcc(v=vs.120).aspx

操作に慣れると 10 分もかからず作れるはずです。

SQL Server が使えれば今回のような問題に悩むことはなくなり、開発工数は激減するはずです。保守工数
も減るはずです。お試しください。

[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87105 ] / ▼[ 87108 ] ▼[ 87115 ]
■87107 / 4階層)  Re[4]: datagridviewからxmlへの出力について
□投稿者/ kaz (8回)-(2018/04/11(Wed) 23:52:35)
No87105 (WebSurfer さん) に返信
> 何故 xml をデータソースに使っているのか分かりませんが、できれば多分 Visual Studio 2017 と一緒に
> インストールされているであろう SQL Server Local DB と Visual Studio のデータソース構成ウィザー
> ドを使って定番の構成のアプリを作ってみてはいかがでしょう?



新しい書き込みを見ずに返信してしまいました
一度書き込んだものを編集するやり方がよくわからないので、追記をここに書きます

データベースを利用したアプリを作るのが初めてなので
ご提示頂いたやり方も調べてみます
xmlを利用した理由は、自分が知っているデータベース形式として
csv、json、xmlがあって、プログラム中で書き換えたりDataGridViewに表示するのに
一番良さそうと思ったからです
つまり深い理由は無いです

趣味で完全独学でやっていることもあって、そもそもアプローチが正しいのかがわからないので
こういう情報をいただけると大変助かります
[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87107 ] / ▼[ 87110 ]
■87108 / 5階層)  Re[5]: datagridviewからxmlへの出力について
□投稿者/ 魔界の仮面弁士 (1640回)-(2018/04/12(Thu) 01:05:12)
No87107 (kaz さん) に返信
> xmlを利用した理由は、自分が知っているデータベース形式として
> csv、json、xmlがあって、プログラム中で書き換えたりDataGridViewに表示するのに
> 一番良さそうと思ったからです
> つまり深い理由は無いです

それだけの話なら、<price> 要素が記録されないことは、些細なことなのでは…。
空要素の price タグを作るために奔走するのは、手段と目的が入れ替わってしまっているようにも感じます。



No87107 (kaz さん) に返信
> xmlを手書きで編集する際に、全要素のひな形が予め存在していたほうが
> 編集しやすいと思ったからです
> xmlを手書き編集する事自体横着だとは思いますが
> 自分で作り、自分だけが使う予定のプログラムなので大目に見ていただければ・・

そのデータファイルは、できれば手書きでも書き換えたいのですよね?

目的に合った形の XML を使いたいのであれば、先にも述べた通り WriteXml / ReadXml に頼らず、
LINQ を使って、型付DataSet ⇔ XML の変換を自前で作ってしまったほうが融通が利くかと。
[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87108 ] / 返信無し
■87110 / 6階層)  Re[6]: datagridviewからxmlへの出力について
□投稿者/ kaz (9回)-(2018/04/12(Thu) 02:47:24)
No87108 (魔界の仮面弁士 さん) に返信

> それだけの話なら、<price> 要素が記録されないことは、些細なことなのでは…。
> 空要素の price タグを作るために奔走するのは、手段と目的が入れ替わってしまっているようにも感じます。

そう言われてしまうと、その通りだと思います
前に質問1に至った経緯でお答えしたとおり
ひな形が出力されていたほうが、手書きで編集しやすいし
自分が使っているxmlを出力するソフトでそういう仕様になっているものがあったので
何かしらちょっとオプションをつければ(例えばスキーマをつけて書き出すオプションの様に)
<price> 要素を出力する方法があるのではないかと思い質問しましたが
思いのほか大変な作業になってしまいました
おそらくそのソフトは、WriteXmlは使わず書き出しているのだと思います

> 目的に合った形の XML を使いたいのであれば、先にも述べた通り WriteXml / ReadXml に頼らず、
> LINQ を使って、型付DataSet ⇔ XML の変換を自前で作ってしまったほうが融通が利くかと。

そういう方法も検討してみます
WriteXmlの1行に多くを求め過ぎですね・・・


色々改善すべき箇所は残っていると思いますが
質問で意図した動作は達成することが出来ましたので
解決済みチェックをつけて締めさせていただきたいと思います
アドバイスしていただいた御二方大変ありがとうございました
解決済み
[ 親 87059 / □ Tree ] 返信 編集キー/

▲[ 87107 ] / 返信無し
■87115 / 5階層)  Re[5]: datagridviewからxmlへの出力について
□投稿者/ WebSurfer (1469回)-(2018/04/12(Thu) 12:23:43)
No87107 (kaz さん) に返信

> xmlを利用した理由は、自分が知っているデータベース形式として
> csv、json、xmlがあって、プログラム中で書き換えたりDataGridViewに表示するのに
> 一番良さそうと思ったからです
> つまり深い理由は無いです

であれば、データベースには SQL Server, My SQL, Access 等を使うことをお勧めします。

もともと、DataSet / DataTable は SQL Server, My SQL, Access 等のデータベース/テーブル
のメモリ上での表現で、非接続型データアクセスで DB の表示・編集・更新を行うためのものの
ようです。

以下の記事の図1、図2を見てもらうとそのあたりのことが一目でわかると思います。

DB 設計者のための明解 ADO.NET 第 1 回
https://msdn.microsoft.com/ja-jp/library/cc482903.aspx

その目的に沿った使い方ができるように Visual Studio でアプリを生成するためのコントロール
やウィーザードが用意されています。

どうしても xml ということでなければ、わざわざ茨の道を進むことはなさそうだと思います。
解決済み
[ 親 87059 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -