トップ回答者
Object datasouce から DataSetを介して、xmlファイルを指定読み込みする方法

質問
-
MSDNのGridView で XML ファイルをデータ ソースとして使いレコードを編集する方法で、
(https://msdn.microsoft.com/ja-jp/library/cc719241.aspx)
xmlファイルをGridviewに表示させたいと考えています。
MSDNのサンプルでは、XmlDataSet.vb 内で、読み込むxmlファイルが固定になっています。
Const strXmlFile As String = "~/App_Data/UserInfo.xml"
xmlファイルのリストのページから、1つを選択すると、そのxmlのデータがGridviewで表示、編集できるようにしたいです。
Default.aspx から別のファイル名を指定し、XmlDataSet.vbに渡す方法を教えてください。
よろしくお願いします。
回答
-
先の私のレスの案、
> SelectParameters として xml ファイルのファイル名を GetDataSet メソッドの引数と
> して渡すようにし、GetDataSet メソッドの中で DataSet を作るようにするというのは、表示するだけならそれでも OK ですが、更新するときにはそれだけでは問題がありました。
UpdateDataSet でも DataSet に xml データを読み込む操作をすれば問題は解決できますが、直すところが多くなってしまうので別の案を考えました。
別の案というのは:
(1) UserInfoTable クラスにファイル名を引数に持つコンストラクタを追加。
(2) ObjectDataSource.ObjectCreating イベントで (1) で追加したコンストラクタを呼び出し、引数に表示・編集したい xml ファイル名を渡す。
ObjectDataSource.ObjectCreating イベント
https://msdn.microsoft.com/ja-jp/library/system.web.ui.webcontrols.objectdatasource.objectcreating(v=vs.100).aspx今度は一応コードを書いて検証してみましたので、ご参考に検証に使ったコード(C# ですが)をアップしておきます。
ビジネスロジック(チュートリアルの XmlDataSet.vb 相当)
using System; using System.Data; using System.Web; using System.ComponentModel; namespace XmlDataSet { public class UserInfoTable : IDisposable { // const を private に変更 private string strXmlFile = "~/App_Data/UserInfo.xml"; private DataSet myDataSet; public UserInfoTable() { myDataSet = new DataSet(); myDataSet.Locale = System.Globalization.CultureInfo.InvariantCulture; string filePath = HttpContext.Current.Server.MapPath(strXmlFile); myDataSet.ReadXml(filePath); } // ファイル名を引数に持つコンストラクタを追加 public UserInfoTable(string filename) { this.strXmlFile = filename; myDataSet = new DataSet(); myDataSet.Locale = System.Globalization.CultureInfo.InvariantCulture; string filePath = HttpContext.Current.Server.MapPath(strXmlFile); myDataSet.ReadXml(filePath); } public virtual void Dispose(bool disposing) { if (disposing) { myDataSet.Dispose(); } } public void Dispose() { Dispose(true); System.GC.SuppressFinalize(this); } ~UserInfoTable() { Dispose(false); } [DataObjectMethod(DataObjectMethodType.Select, true)] public DataSet GetDataSet() { return myDataSet; } [DataObjectMethod(DataObjectMethodType.Update, true)] public void UpdateDataSet(int id, string name) { string strFillter = "ID='" + id.ToString() + "'"; DataRow[] rows = myDataSet.Tables[0].Select(strFillter); if (rows.Length > 0) { rows[0]["NAME"] = name; Save(); } } private void Save() { string filePath = HttpContext.Current.Server.MapPath(strXmlFile); myDataSet.WriteXml(filePath, XmlWriteMode.IgnoreSchema); } } }
aspx ページ(チュートリアルの Default.aspx 相当)
オリジナル(ObjectDataSource1 + GridView1)とファイル名を指定できるもの(ObjectDataSource2 + GridView2)の両方を含んでいます。
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> private string filename = "~/App_Data/UserInfo2.xml"; protected void ObjectDataSource2_ObjectCreating( object sender, ObjectDataSourceEventArgs e) { XmlDataSet.UserInfoTable userinfo = new XmlDataSet.UserInfoTable(filename); e.ObjectInstance = userinfo; } </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <h1>オリジナル</h1> <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="GetDataSet" TypeName="XmlDataSet.UserInfoTable" UpdateMethod="UpdateDataSet"> <UpdateParameters> <asp:Parameter Name="id" Type="Int32" /> <asp:Parameter Name="name" Type="String" /> </UpdateParameters> </asp:ObjectDataSource> <asp:GridView ID="GridView1" runat="server" AutoGenerateEditButton="True" DataSourceID="ObjectDataSource1"> </asp:GridView> <h1>ファイルを指定</h1> <asp:ObjectDataSource ID="ObjectDataSource2" runat="server" SelectMethod="GetDataSet" TypeName="XmlDataSet.UserInfoTable" UpdateMethod="UpdateDataSet" OnObjectCreating="ObjectDataSource2_ObjectCreating"> <UpdateParameters> <asp:Parameter Name="id" Type="Int32" /> <asp:Parameter Name="name" Type="String" /> </UpdateParameters> </asp:ObjectDataSource> <asp:GridView ID="GridView2" runat="server" AutoGenerateEditButton="True" DataSourceID="ObjectDataSource2"> </asp:GridView> </form> </body> </html>
-
Default.aspx から別のファイル名を指定し、XmlDataSet.vbに渡す方法を教えてください。
ObjectDataSourceのSelectMethodのパラメータとして渡すようにしてみました。
Imports Microsoft.VisualBasic Imports System.Data Imports System.Web Namespace XmlDataSet Public Class UserInfoTable Implements IDisposable Dim strXmlFile As String Private myDataSet As DataSet Sub New() myDataSet = HttpContext.Current.Session("myDataSet") strXmlFile = HttpContext.Current.Session("strXmlFile") End Sub Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean) If myDataSet IsNot Nothing AndAlso disposing Then myDataSet.Dispose() End If End Sub Public Overloads Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub Protected Overrides Sub Finalize() Dispose(False) End Sub Public Function GetDataSet(ByVal filename As String) As DataSet 'ファイルの存在チェック If Not System.IO.File.Exists(HttpContext.Current.Server.MapPath(filename)) Then Return Nothing End If ' DataSet を返す myDataSet = New DataSet myDataSet.Locale = Globalization.CultureInfo.InvariantCulture ' 仮想パスから物理パスを取得する Dim filePath As String filePath = HttpContext.Current.Server.MapPath(filename) ' XML データを DataSet へ読み込む myDataSet.ReadXml(filePath) HttpContext.Current.Session("myDataSet") = myDataSet HttpContext.Current.Session("strXmlFile") = filename Return myDataSet End Function Public Sub UpdateDataSet(ByVal ID As Integer, ByVal NAME As String) ' ID が一致するレコードを取得する Dim rows() As Data.DataRow Dim strFillter As String strFillter = "ID=" + ID.ToString(Globalization.CultureInfo.CurrentCulture) rows = myDataSet.Tables(0).Select(strFillter) If rows.Length > 0 Then ' DataSet の値を更新し、XML ファイルへ保存する rows(0)("NAME") = NAME Save() End If End Sub Private Sub Save() Dim filePath As String filePath = HttpContext.Current.Server.MapPath(strXmlFile) myDataSet.WriteXml(filePath, XmlWriteMode.IgnoreSchema) End Sub End Class End Namespace
aspxのコードビハインド
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ObjectDataSource1.SelectParameters("filename").DefaultValue = "~/App_Data/UserInfo2.xml" End Sub
aspx
<body> <form id="MyForm" runat="server"> <div> <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="GetDataSet" TypeName="XmlDataSet.UserInfoTable" UpdateMethod="UpdateDataSet"> <SelectParameters> <asp:Parameter Name="filename" Type="String" /> </SelectParameters> <UpdateParameters> <asp:Parameter Name="ID" Type="Int32" /> <asp:Parameter Name="NAME" Type="String" /> </UpdateParameters> </asp:ObjectDataSource> <asp:GridView ID="GridView1" runat="server" DataSourceID="ObjectDataSource1" AutoGenerateEditButton="True"> </asp:GridView> </div> <asp:Button ID="Button1" runat="server" Text="Button" /> </form> </body>
★良い回答には回答済みマークを付けよう! MVP - .NET http://d.hatena.ne.jp/trapemiya/
すべての返信
-
検証等はしてませんので単なるアイデア(と言うより思いつきレベル)ですが・・・
> Default.aspx から別のファイル名を指定し、XmlDataSet.vbに渡す方法を教えてください。
SelectParameters として xml ファイルのファイル名を GetDataSet メソッドの引数として渡すようにし、GetDataSet メソッドの中で DataSet を作るようにする(チュートリアルではコンストラクタで DataSet を作っていますがそれは止めて)というのはいかがですか?
#質問する際は、一番最初に、ご自分の環境(OS, .NET, IIS, Visual Studio のバージョン、DB サーバーとそのバージョン、ブラウザを使っているなら何かなど)に関する情報を最低書いていただけませんか?
適切に情報が提供されていれば、回答者が質問者さんの状況を的確に把握でき、タイムリーで的を得た回答が得られるということで、質問者さんにもメリットがあります。ガイドラインも出ていますので目を通していただければと思います。
フォーラムのご利用方法(質問の投稿)について
https://social.technet.microsoft.com/Forums/ja-JP/home?forum=announceja&announcementId=587d27f8-adc8-432a-905c-81375f8a05ec -
先の私のレスの案、
> SelectParameters として xml ファイルのファイル名を GetDataSet メソッドの引数と
> して渡すようにし、GetDataSet メソッドの中で DataSet を作るようにするというのは、表示するだけならそれでも OK ですが、更新するときにはそれだけでは問題がありました。
UpdateDataSet でも DataSet に xml データを読み込む操作をすれば問題は解決できますが、直すところが多くなってしまうので別の案を考えました。
別の案というのは:
(1) UserInfoTable クラスにファイル名を引数に持つコンストラクタを追加。
(2) ObjectDataSource.ObjectCreating イベントで (1) で追加したコンストラクタを呼び出し、引数に表示・編集したい xml ファイル名を渡す。
ObjectDataSource.ObjectCreating イベント
https://msdn.microsoft.com/ja-jp/library/system.web.ui.webcontrols.objectdatasource.objectcreating(v=vs.100).aspx今度は一応コードを書いて検証してみましたので、ご参考に検証に使ったコード(C# ですが)をアップしておきます。
ビジネスロジック(チュートリアルの XmlDataSet.vb 相当)
using System; using System.Data; using System.Web; using System.ComponentModel; namespace XmlDataSet { public class UserInfoTable : IDisposable { // const を private に変更 private string strXmlFile = "~/App_Data/UserInfo.xml"; private DataSet myDataSet; public UserInfoTable() { myDataSet = new DataSet(); myDataSet.Locale = System.Globalization.CultureInfo.InvariantCulture; string filePath = HttpContext.Current.Server.MapPath(strXmlFile); myDataSet.ReadXml(filePath); } // ファイル名を引数に持つコンストラクタを追加 public UserInfoTable(string filename) { this.strXmlFile = filename; myDataSet = new DataSet(); myDataSet.Locale = System.Globalization.CultureInfo.InvariantCulture; string filePath = HttpContext.Current.Server.MapPath(strXmlFile); myDataSet.ReadXml(filePath); } public virtual void Dispose(bool disposing) { if (disposing) { myDataSet.Dispose(); } } public void Dispose() { Dispose(true); System.GC.SuppressFinalize(this); } ~UserInfoTable() { Dispose(false); } [DataObjectMethod(DataObjectMethodType.Select, true)] public DataSet GetDataSet() { return myDataSet; } [DataObjectMethod(DataObjectMethodType.Update, true)] public void UpdateDataSet(int id, string name) { string strFillter = "ID='" + id.ToString() + "'"; DataRow[] rows = myDataSet.Tables[0].Select(strFillter); if (rows.Length > 0) { rows[0]["NAME"] = name; Save(); } } private void Save() { string filePath = HttpContext.Current.Server.MapPath(strXmlFile); myDataSet.WriteXml(filePath, XmlWriteMode.IgnoreSchema); } } }
aspx ページ(チュートリアルの Default.aspx 相当)
オリジナル(ObjectDataSource1 + GridView1)とファイル名を指定できるもの(ObjectDataSource2 + GridView2)の両方を含んでいます。
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> private string filename = "~/App_Data/UserInfo2.xml"; protected void ObjectDataSource2_ObjectCreating( object sender, ObjectDataSourceEventArgs e) { XmlDataSet.UserInfoTable userinfo = new XmlDataSet.UserInfoTable(filename); e.ObjectInstance = userinfo; } </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <h1>オリジナル</h1> <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="GetDataSet" TypeName="XmlDataSet.UserInfoTable" UpdateMethod="UpdateDataSet"> <UpdateParameters> <asp:Parameter Name="id" Type="Int32" /> <asp:Parameter Name="name" Type="String" /> </UpdateParameters> </asp:ObjectDataSource> <asp:GridView ID="GridView1" runat="server" AutoGenerateEditButton="True" DataSourceID="ObjectDataSource1"> </asp:GridView> <h1>ファイルを指定</h1> <asp:ObjectDataSource ID="ObjectDataSource2" runat="server" SelectMethod="GetDataSet" TypeName="XmlDataSet.UserInfoTable" UpdateMethod="UpdateDataSet" OnObjectCreating="ObjectDataSource2_ObjectCreating"> <UpdateParameters> <asp:Parameter Name="id" Type="Int32" /> <asp:Parameter Name="name" Type="String" /> </UpdateParameters> </asp:ObjectDataSource> <asp:GridView ID="GridView2" runat="server" AutoGenerateEditButton="True" DataSourceID="ObjectDataSource2"> </asp:GridView> </form> </body> </html>
-
Default.aspx から別のファイル名を指定し、XmlDataSet.vbに渡す方法を教えてください。
ObjectDataSourceのSelectMethodのパラメータとして渡すようにしてみました。
Imports Microsoft.VisualBasic Imports System.Data Imports System.Web Namespace XmlDataSet Public Class UserInfoTable Implements IDisposable Dim strXmlFile As String Private myDataSet As DataSet Sub New() myDataSet = HttpContext.Current.Session("myDataSet") strXmlFile = HttpContext.Current.Session("strXmlFile") End Sub Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean) If myDataSet IsNot Nothing AndAlso disposing Then myDataSet.Dispose() End If End Sub Public Overloads Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub Protected Overrides Sub Finalize() Dispose(False) End Sub Public Function GetDataSet(ByVal filename As String) As DataSet 'ファイルの存在チェック If Not System.IO.File.Exists(HttpContext.Current.Server.MapPath(filename)) Then Return Nothing End If ' DataSet を返す myDataSet = New DataSet myDataSet.Locale = Globalization.CultureInfo.InvariantCulture ' 仮想パスから物理パスを取得する Dim filePath As String filePath = HttpContext.Current.Server.MapPath(filename) ' XML データを DataSet へ読み込む myDataSet.ReadXml(filePath) HttpContext.Current.Session("myDataSet") = myDataSet HttpContext.Current.Session("strXmlFile") = filename Return myDataSet End Function Public Sub UpdateDataSet(ByVal ID As Integer, ByVal NAME As String) ' ID が一致するレコードを取得する Dim rows() As Data.DataRow Dim strFillter As String strFillter = "ID=" + ID.ToString(Globalization.CultureInfo.CurrentCulture) rows = myDataSet.Tables(0).Select(strFillter) If rows.Length > 0 Then ' DataSet の値を更新し、XML ファイルへ保存する rows(0)("NAME") = NAME Save() End If End Sub Private Sub Save() Dim filePath As String filePath = HttpContext.Current.Server.MapPath(strXmlFile) myDataSet.WriteXml(filePath, XmlWriteMode.IgnoreSchema) End Sub End Class End Namespace
aspxのコードビハインド
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ObjectDataSource1.SelectParameters("filename").DefaultValue = "~/App_Data/UserInfo2.xml" End Sub
aspx
<body> <form id="MyForm" runat="server"> <div> <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="GetDataSet" TypeName="XmlDataSet.UserInfoTable" UpdateMethod="UpdateDataSet"> <SelectParameters> <asp:Parameter Name="filename" Type="String" /> </SelectParameters> <UpdateParameters> <asp:Parameter Name="ID" Type="Int32" /> <asp:Parameter Name="NAME" Type="String" /> </UpdateParameters> </asp:ObjectDataSource> <asp:GridView ID="GridView1" runat="server" DataSourceID="ObjectDataSource1" AutoGenerateEditButton="True"> </asp:GridView> </div> <asp:Button ID="Button1" runat="server" Text="Button" /> </form> </body>
★良い回答には回答済みマークを付けよう! MVP - .NET http://d.hatena.ne.jp/trapemiya/