none
ListViewでチェックされた値をXMLファイルから読み込む方法

    質問

  • ListViewでチェックされた値をXMLファイルから読み込む方法がわかりません。

    <xml>

    <User>

    <FullName>田中</FullName>

    <Age>20</Age>

    <Address>千葉</Address>

    <Mail>sample @sample. com</Mail>

    <FullName>鈴木</FullName>

    <Age>23</Age>

    <Address>新潟</Address>

    <Mail>sample @sample2. com</Mail>

    <FullName>小澤</FullName>

    <Age>34</Age>

    <Address>兵庫</Address>

    <Mail>sample2@sample. com</Mail>

    ....

    </User>

    </xml>

    フォームロード時にこのようなXMLファイルを読み込んで、FullNameとAgeだけListViewに追加します。

    その後、チェックされたユーザーの情報全てをXMLファイルから読み込んで別フォームに入力して処理させたいのですが、どう書けばいいのかわかりません。

    ご教示ください。

    2015年2月5日 20:35

回答

  • おお、これは失礼しました。
    思い込んでました。

    WinFormsでListViewをあまり使ったことが無いのでベストプラクティスがわかりませんが、
    Tagにオブジェクトを格納してやれば良いんじゃないでしょうか。(データバインドが出来れば良いと思うんですが良いサンプルが見当たりませんでした)

        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
    
                list.GridLines = true;
                list.View = View.Details;
                list.Columns.Add("FullName");
                list.Columns.Add("Age");
                list.CheckBoxes = true;
                var user1 = new User() { FullName = "田中1", Age = 20, Address = "千葉1" };
                var user2 = new User() { FullName = "田中2", Age = 21, Address = "千葉2" };
                var user3 = new User() { FullName = "田中3", Age = 22, Address = "千葉3" };
                list.Items.Add(new UserItem(user1));
                list.Items.Add(new UserItem(user2));
                list.Items.Add(new UserItem(user3)); 
            }
    
            private class UserItem : ListViewItem
            {
                public UserItem(User args)
                {
                    this.Text = args.FullName;
                    this.SubItems.Add(args.Age.ToString());
                    this.Tag = args;
                }
                public User GetUser()
                {
                    return (User)this.Tag;
                }
            }
    
            public class User
            {
                public string FullName { get; set; }
                public int Age { get; set; }
                public string Address { get; set; }
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                var hoge = list.CheckedItems;
                foreach(UserItem current in hoge)
                {
                    var currentUser = current.GetUser();
                    Console.WriteLine("FullName : " + currentUser.FullName);
                    Console.WriteLine("Age : " + currentUser.Age);
                    Console.WriteLine("Address : " + currentUser.Address);
                }
            }
        }


    2015年2月6日 1:00
    モデレータ
  • XMLのレイアウトが厳密に決まっているのか、それとも保存できれば良いのかによって変わりますが、
    とりあえず保存するならシリアライズすれば良いです。

            private void ひとつずつ保存_Click(object sender, EventArgs e)
            {
                var currentUser = ((UserItem)list.CheckedItems[0]).GetUser();
                var serializer = new System.Xml.Serialization.XmlSerializer(typeof(User));
                using (var writer = new System.IO.StreamWriter(@"C:\hoge1.xml"))
                {
                    serializer.Serialize(writer, currentUser);
                }
            }
            //↓例として選択した1件目がこう出力される
            //<?xml version="1.0" encoding="utf-8"?>
            //<User xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            //  <FullName>田中2</FullName>
            //  <Age>21</Age>
            //  <Address>千葉2</Address>
            //</User>
    
            private void リストで保存_Click(object sender, EventArgs e)
            {
                var listUser = new List<User>();
                foreach (UserItem current in list.CheckedItems)
                {
                    listUser.Add(current.GetUser());
                }
                var serializer = new System.Xml.Serialization.XmlSerializer(typeof(List<User>));
                using (var writer = new System.IO.StreamWriter(@"C:\hoge2.xml"))
                {
                    serializer.Serialize(writer, listUser);
                }
            }
            //↓選択したアイテムがこう出力される
            //<?xml version="1.0" encoding="utf-8"?>
            //<ArrayOfUser xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            //  <User>
            //    <FullName>田中2</FullName>
            //    <Age>21</Age>
            //    <Address>千葉2</Address>
            //  </User>
            //  <User>
            //    <FullName>田中3</FullName>
            //    <Age>22</Age>
            //    <Address>千葉3</Address>
            //  </User>
            //</ArrayOfUser>

    出力したXMLを読み込みたい場合はデシリアライズします。
    どぼんさんのページが参考になりますでしょうか。

    http://dobon.net/vb/dotnet/file/xmlserializer.html


    2015年2月6日 3:50
    モデレータ
  • 解決されたようですが、LINQ TO XMLを使用した例を載せておきます。なお、LINQ TO XMLのサンプルのため、焦点を明確にするために、一部ご希望の仕様から変更しています。

    //表示する画面
    public partial class XmlRead : Form
    {
        XDocument xmlDoc;
    
        public XmlRead()
        {
            InitializeComponent();
        }
    
        private void bttn_Load_Click(object sender, EventArgs e)
        {
            xmlDoc = XDocument.Load(@"c:\work\user.xml");
            var q = from c in xmlDoc.Root.Descendants("User")
                    select new
                    {
                        Name = c.Element("FullName").Value,
                        Age = c.Element("Age").Value,
                        //Address = c.Element("Address").Value,
                        //Mail = c.Element("Mail").Value
                    };
    
            dataGridView1.DataSource = q.ToList();
        }
    
        private void bttn_edit_Click(object sender, EventArgs e)
        {
            var f = new XmlReadEdit(dataGridView1.SelectedRows[0].Index, xmlDoc);
            f.Show();
        }
    
        private void bttn_WriteToFile_Click(object sender, EventArgs e)
        {
            xmlDoc.Save(@"c:\work\user.xml");
        }
    }

    //編集する画面
    public partial class XmlReadEdit : Form
    {
        XDocument xmlDoc;
        List<User> list = new List<User>();
        XElement el;
    
        public XmlReadEdit(int rowIndex, XDocument xmlDoc)
        {
            InitializeComponent();
    
            this.xmlDoc = xmlDoc;
    
            el = xmlDoc.Descendants("User").ElementAt(rowIndex);
    
            list.Add(new User(){
                        Name = el.Element("FullName").Value,
                        Age = el.Element("Age").Value,
                        Address = el.Element("Address").Value,
                        Mail = el.Element("Mail").Value
            });
    
            dataGridView1.DataSource = list;
        }
    
        private void bttn_save_Click(object sender, EventArgs e)
        {
            el.Element("FullName").Value = list[0].Name;
            el.Element("Age").Value = list[0].Age;
            el.Element("Address").Value = list[0].Address;
            el.Element("Mail").Value = list[0].Mail;
        }
    }
    
    class User
    {
        public string Name { get; set; }
        public string Age { get; set; }
        public string Address { get; set; }
        public string Mail { get; set; }
    }


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク Sankarea255 2015年2月7日 21:15
    2015年2月6日 6:49
    モデレータ

すべての返信

  • 1例としては以下の流れが考えられます。

    1. 最初の読み込みのタイミングで FullName から Mail までセットで読み込んでおき、それを1つのクラスに格納する。
    2. ListView には FullName と Age だけを表示する。
    3. 選択されたアイテムを元に1で作ったクラスのオブジェクトを取り出す。
    4. 別フォームにそのオブジェクトを渡し、別フォームはオブジェクトを受け取って表示に反映する。

    どのあたりまではわかり、どのあたりはわからないという状態ですか?

    2015年2月5日 22:33
    モデレータ
  • ご回答ありがとうございます。

    3番が分からない状態です。

    1,2,4はなんとなくわかります...


    2015年2月5日 23:33
  • こんにちは。
    XML読み込み済みだと仮定して、とりあえずコードビハインドで。

        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                users.Add(new User() { IsSelect = true, FullName = "田中1", Age = 20, Address = "千葉1" });
                users.Add(new User() { IsSelect = false, FullName = "田中2", Age = 21, Address = "千葉2" });
                users.Add(new User() { IsSelect = false, FullName = "田中3", Age = 22, Address = "千葉3" });
                list.ItemsSource = users;
            }
    
            List<User> users = new List<User>();
            public class User
            {
                public bool IsSelect { get; set; }
                public string FullName { get; set; }
                public int Age { get; set; }
                public string Address { get; set; }
            }
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                var checkedList = users.Where(x => x.IsSelect);
                //送ったりする
            }
        }
    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition Height="100" />
            </Grid.RowDefinitions>
            <ListView x:Name="list">
                <ListView.View>
                    <GridView>
                        <GridViewColumn>
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <CheckBox IsChecked="{Binding IsSelect}" />
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Header="FullName" DisplayMemberBinding="{Binding FullName}" />
                        <GridViewColumn Header="Age" DisplayMemberBinding="{Binding Age}" />
                    </GridView>
                </ListView.View>
            </ListView>
            <Button Content="Send" Grid.Row="1" Click="Button_Click" />
        </Grid>
    </Window>





    2015年2月6日 0:31
    モデレータ
  • ご回答ありがとうございます。

    WPFではなく、普通のWindows フォームです。

    2015年2月6日 0:55
  • おお、これは失礼しました。
    思い込んでました。

    WinFormsでListViewをあまり使ったことが無いのでベストプラクティスがわかりませんが、
    Tagにオブジェクトを格納してやれば良いんじゃないでしょうか。(データバインドが出来れば良いと思うんですが良いサンプルが見当たりませんでした)

        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
    
                list.GridLines = true;
                list.View = View.Details;
                list.Columns.Add("FullName");
                list.Columns.Add("Age");
                list.CheckBoxes = true;
                var user1 = new User() { FullName = "田中1", Age = 20, Address = "千葉1" };
                var user2 = new User() { FullName = "田中2", Age = 21, Address = "千葉2" };
                var user3 = new User() { FullName = "田中3", Age = 22, Address = "千葉3" };
                list.Items.Add(new UserItem(user1));
                list.Items.Add(new UserItem(user2));
                list.Items.Add(new UserItem(user3)); 
            }
    
            private class UserItem : ListViewItem
            {
                public UserItem(User args)
                {
                    this.Text = args.FullName;
                    this.SubItems.Add(args.Age.ToString());
                    this.Tag = args;
                }
                public User GetUser()
                {
                    return (User)this.Tag;
                }
            }
    
            public class User
            {
                public string FullName { get; set; }
                public int Age { get; set; }
                public string Address { get; set; }
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                var hoge = list.CheckedItems;
                foreach(UserItem current in hoge)
                {
                    var currentUser = current.GetUser();
                    Console.WriteLine("FullName : " + currentUser.FullName);
                    Console.WriteLine("Age : " + currentUser.Age);
                    Console.WriteLine("Address : " + currentUser.Address);
                }
            }
        }


    2015年2月6日 1:00
    モデレータ
  • 迅速なご回答ありがとうございます。

    今まではアイテムを追加、編集、削除してListViewに表示されているアイテムをすべてXMLに保存していたのですが、このような書き方の場合、XMLに保存するにはどのようにすればいいでしょうか?



    2015年2月6日 3:32
  • XMLのレイアウトが厳密に決まっているのか、それとも保存できれば良いのかによって変わりますが、
    とりあえず保存するならシリアライズすれば良いです。

            private void ひとつずつ保存_Click(object sender, EventArgs e)
            {
                var currentUser = ((UserItem)list.CheckedItems[0]).GetUser();
                var serializer = new System.Xml.Serialization.XmlSerializer(typeof(User));
                using (var writer = new System.IO.StreamWriter(@"C:\hoge1.xml"))
                {
                    serializer.Serialize(writer, currentUser);
                }
            }
            //↓例として選択した1件目がこう出力される
            //<?xml version="1.0" encoding="utf-8"?>
            //<User xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            //  <FullName>田中2</FullName>
            //  <Age>21</Age>
            //  <Address>千葉2</Address>
            //</User>
    
            private void リストで保存_Click(object sender, EventArgs e)
            {
                var listUser = new List<User>();
                foreach (UserItem current in list.CheckedItems)
                {
                    listUser.Add(current.GetUser());
                }
                var serializer = new System.Xml.Serialization.XmlSerializer(typeof(List<User>));
                using (var writer = new System.IO.StreamWriter(@"C:\hoge2.xml"))
                {
                    serializer.Serialize(writer, listUser);
                }
            }
            //↓選択したアイテムがこう出力される
            //<?xml version="1.0" encoding="utf-8"?>
            //<ArrayOfUser xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            //  <User>
            //    <FullName>田中2</FullName>
            //    <Age>21</Age>
            //    <Address>千葉2</Address>
            //  </User>
            //  <User>
            //    <FullName>田中3</FullName>
            //    <Age>22</Age>
            //    <Address>千葉3</Address>
            //  </User>
            //</ArrayOfUser>

    出力したXMLを読み込みたい場合はデシリアライズします。
    どぼんさんのページが参考になりますでしょうか。

    http://dobon.net/vb/dotnet/file/xmlserializer.html


    2015年2月6日 3:50
    モデレータ
  • 無事に解決しました。

    ありがとうございました。

    2015年2月6日 5:14
  • 解決されたようですが、LINQ TO XMLを使用した例を載せておきます。なお、LINQ TO XMLのサンプルのため、焦点を明確にするために、一部ご希望の仕様から変更しています。

    //表示する画面
    public partial class XmlRead : Form
    {
        XDocument xmlDoc;
    
        public XmlRead()
        {
            InitializeComponent();
        }
    
        private void bttn_Load_Click(object sender, EventArgs e)
        {
            xmlDoc = XDocument.Load(@"c:\work\user.xml");
            var q = from c in xmlDoc.Root.Descendants("User")
                    select new
                    {
                        Name = c.Element("FullName").Value,
                        Age = c.Element("Age").Value,
                        //Address = c.Element("Address").Value,
                        //Mail = c.Element("Mail").Value
                    };
    
            dataGridView1.DataSource = q.ToList();
        }
    
        private void bttn_edit_Click(object sender, EventArgs e)
        {
            var f = new XmlReadEdit(dataGridView1.SelectedRows[0].Index, xmlDoc);
            f.Show();
        }
    
        private void bttn_WriteToFile_Click(object sender, EventArgs e)
        {
            xmlDoc.Save(@"c:\work\user.xml");
        }
    }

    //編集する画面
    public partial class XmlReadEdit : Form
    {
        XDocument xmlDoc;
        List<User> list = new List<User>();
        XElement el;
    
        public XmlReadEdit(int rowIndex, XDocument xmlDoc)
        {
            InitializeComponent();
    
            this.xmlDoc = xmlDoc;
    
            el = xmlDoc.Descendants("User").ElementAt(rowIndex);
    
            list.Add(new User(){
                        Name = el.Element("FullName").Value,
                        Age = el.Element("Age").Value,
                        Address = el.Element("Address").Value,
                        Mail = el.Element("Mail").Value
            });
    
            dataGridView1.DataSource = list;
        }
    
        private void bttn_save_Click(object sender, EventArgs e)
        {
            el.Element("FullName").Value = list[0].Name;
            el.Element("Age").Value = list[0].Age;
            el.Element("Address").Value = list[0].Address;
            el.Element("Mail").Value = list[0].Mail;
        }
    }
    
    class User
    {
        public string Name { get; set; }
        public string Age { get; set; }
        public string Address { get; set; }
        public string Mail { get; set; }
    }


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク Sankarea255 2015年2月7日 21:15
    2015年2月6日 6:49
    モデレータ
  • ありがとうございます。参考にさせていただきます。
    2015年2月7日 21:15