none
Object datasouce から DataSetを介して、xmlファイルを指定読み込みする方法 RRS feed

  • 質問

  • 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に渡す方法を教えてください。

    よろしくお願いします。

    2016年1月3日 8:27

回答

  • 先の私のレスの案、

    > 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>
    

    • 回答の候補に設定 星 睦美 2016年1月14日 6:01
    • 回答としてマーク 星 睦美 2016年1月22日 7:47
    2016年1月4日 8:22
  • 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/

    • 回答の候補に設定 星 睦美 2016年1月14日 6:01
    • 回答としてマーク 星 睦美 2016年1月22日 7:47
    2016年1月5日 6:33
    モデレータ

すべての返信

  • 検証等はしてませんので単なるアイデア(と言うより思いつきレベル)ですが・・・

    > 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

    2016年1月3日 9:32
  • 先の私のレスの案、

    > 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>
    

    • 回答の候補に設定 星 睦美 2016年1月14日 6:01
    • 回答としてマーク 星 睦美 2016年1月22日 7:47
    2016年1月4日 8:22
  • 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/

    • 回答の候補に設定 星 睦美 2016年1月14日 6:01
    • 回答としてマーク 星 睦美 2016年1月22日 7:47
    2016年1月5日 6:33
    モデレータ
  • こんにちは、フォーラム オペレーターの星 睦美です。
    J6548 さんからの質問にフォーラムのユーザーから回答がありますので、内容を確認いただいて返信いただければと思います。

    フォーラムでの今後の回答の励みになりますので、参考になる回答には投稿者からの[回答としてマーク] をお願いします。


    フォーラム オペレーター 星 睦美 - MSDN Community Support

    2016年1月14日 6:05