直列つなぎ。 -とある発達障害者の記録

知識と知識を繋ぐためのblog。 広汎性発達と診断されました。ぜんぜん役に立ってないけど。月収13万円、家賃4万円で生活するひつじ人間。

XMLクラスを使用して設定の保存と読み込みを行う

 行動履歴 
   8.1 button4(FormsPropatySave_Click) 追加



 概要
  つい最近更新された
   C#で付箋紙を作る(第四回目) データの数だけ付箋紙を起動する  
  というエントリを利用して設定のloadとsaveを行うアルゴリズムを考える(付箋ソフト用処理)。

本音を言うとかなり助かる。でも、スタンドアロン型では無理があるとおもうんだよねー。 多重起動をいくつもやるのと同じなわけで。 処理が重いしメモリも食う。 最終的にIE並みに重くなると思う。
 

特にload時にこれをやるのは低スペックPCでは適さない。
 作者の考えは知らないが、C# にはopenFormsプロパティが実装されており、これにより明示的なインスタンス化無しで、nameプロパティや番号で各フォームにアクセスが可能になっている。 
 
     Windowsフォームでフォームのコレクションを使用するには?
                         動作確認済み。
     [C#]開いているフォームインスタンス参照     



 ・・・という訳で、オレは不可視のメインフォーム経由で行おうと思う。
 目的が同じでも、アプローチが異なるとどうなるのか。


 今回のサンプルでは、XMLファイル内には取得したファイル名を使い、リッチテキストファイルのloadを行う事にする。
フォント情報はrtfファイル内で扱うため、わざわざXML内に組み込む必要がない。  




 【処理】
 a. クラスに格納したXMLエレメントをシリアライズして保存(XMLファイルとして保存)
 逆にデシリアライズして読み込みという処理を行う。
 
 なお、シリアライズとは、プログラムがメモリ上に存在するデータを保存出来るように変換する処理の事。


 load時
      private void Form1_Load(object sender, EventArgs e)
        {
            setCurrent = Directory.GetCurrentDirectory();
          
        }


  用意するXMLクラス
   [XmlRoot("Sticky")]
        public class StickyData
        {
          
            public string FileName { get; set; }
       
            public int Width { get; set; }
     
            public int Height { get; set; }
    
            public int Top { get; set; }
        
            public int Left { get; set; }
    
            public Color RTFColor { get; set; }
          
          
        }

   /// <summary>
        /// StickyDataをジェネリックリスト化するクラス
        ///つまり連続したXMLリストを作る
  /// </summary>
        [XmlRoot("Stickys")]
        public class StickyList
        {
            [XmlElement("Sticky")]
            public List<StickyData> DataList { get; set; }
        }





 b-1. ディレクトリ下にあるファイル名(rtf)を列挙 (button1)


スコープ外
    string setCurrent;
        StickyList SL;
        StickyData SD;


        /// <summary>
        /// カレントディレクトリ下にある”Data”フォルダ内のファイル名を列挙
        /// </summary>
 private void button1_Click(object sender, EventArgs e)
        {

  setCurrent = Directory.GetCurrentDirectory();       
            string[] files = Directory.GetFiles(setCurrent +"\\Data\\", "*.rtf", SearchOption.TopDirectoryOnly);

  ///

            foreach (string filename in files)
            {
                string s = Path.GetFileName(filename);
                listBox1.Items.Add(s);



                SL.DataList.Add(SD);  //SD内は正常に取得できている 下記”不具合”参照
          //Sticky List にStickyDataを追加する。
            }
   }


 b-2
   上記で取得したファイル名をXMLとして保存 (button 2)
   
 private void button2_Click(object sender, EventArgs e)
        {
            var serializer = new XmlSerializer(typeof(StickyList));
            //"sticky Data"をシリアライズクラスを初期化(インスタンス化)


            var sw = new StreamWriter(@"Sticky.xml", false, new UTF8Encoding(false));
            serializer.Serialize(sw, SL);  //変数”SL”内は最後に取得したファイル名に統一されてしまう。
            //シリアライズ

            sw.Close();
  }

  不具合
   最後のファイル名しか反映されない。
  Form1.rtf ~ Form4.rtfがある場合、Form4.rtfしかファイル名として保存されない。
 (要素数.countは反映される)

  SD内は正常に取得できている
  

  出力結果 
   <?xml version="1.0" encoding="utf-8"?>
<Stickys xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Sticky>
    <FileName>Form4.rtf</FileName>
    <width>0</width>
    <height>0</height>
    <top>0</top>
    <left>0</left>
    <ForeColor />
  </Sticky>
  <Sticky>
    <FileName>Form4.rtf</FileName>
    <width>0</width>
    <height>0</height>
    <top>0</top>
    <left>0</left>
    <ForeColor />
  </Sticky>
  <Sticky>
    <FileName>Form4.rtf</FileName>
    <width>0</width>
    <height>0</height>
    <top>0</top>
    <left>0</left>
    <ForeColor />
  </Sticky>
  <Sticky>
    <FileName>Form4.rtf</FileName>
    <width>0</width>
    <height>0</height>
    <top>0</top>
    <left>0</left>
    <ForeColor />
  </Sticky>
</Stickys>
 
 解法
   foreach内でその都度new する必要がある。
   
               foreach (string filename in files)
            {
   
                string s = Path.GetFileName(filename);
                listBox1.Items.Add(s);


           var SD = new StickeData();  //その都度初期化

                SL.DataList.Add(SD);  //SD内は正常に取得できている 下記”不具合”参照
          //Sticky List にStickyDataを追加する。
            }
   

  質問
   ジェネリッククラスに要素を追加すると、最後のファイル名のみ反映されてしまう    
        > ListへのaddはSDのデータではなく、SDへのポインタがaddされるだけです。
                                        とのこと。
 




 b-3 残りのプロパティ(width,Height,top,Left,ForeColor)をXMLとして保存 (button3)


  Color情報のセット
        private void Form1_Load(object sender, EventArgs e)
        {
            setCurrent = Directory.GetCurrentDirectory();

            string[] ColorNames = { "AliceBlue","Beige","CabetBlue", "DarkGray"};

            foreach (string colorSt in ColorNames )
            {
                listBox1.Items.Add(colorSt);
            }

        }
  
    private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if((string)listBox1.SelectedItem == "AliceBlue")
            {
                richTextBox1.BackColor = Color.AliceBlue;
            }
             else if ((string)listBox1.SelectedItem == "Beige")
            {
                richTextBox1.BackColor = Color.Beige;


            }
            else if ((string)listBox1.SelectedItem == "CabetBlue")
            {
                richTextBox1.BackColor = Color.CadetBlue;


            }

            else if ((string)listBox1.SelectedItem == "DarkGray")
            {
                richTextBox1.BackColor = Color.DarkGray;


            }

 
 ------------------------------------------

        /// <summary>
        /// 残りのプロパティを保存
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            var SD = new StickyData();
             SL = new StickyList();
            SL.DataList = new List<StickyData>();
            //データリスト初期化

            SD.FileName = Name+ ".rtf";
            SD.Height = Height;
            SD.Width = Width;
            SD.Top = Top;
            SD.Left = Left;
            SD.BackColor = richTextBox1.BackColor.Name;

            SL.DataList.Add(SD);


        }
出力結果
<?xml version="1.0" encoding="utf-8"?>
<StickyList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Sticky>
    <FileName>Form1.rtf</FileName>
    <Width>415</Width>
    <Height>300</Height>
    <Top>130</Top>
    <Left>130</Left>
    <BackColor>Beige</BackColor>
  </Sticky>
</StickyList>



 b-4 プロパティの保存を複数のフォームについて行う(b-1 + b-3)
   OpenFormsプロパティを使用して行う。

   /// <summary>
        /// Formを生成するbutton
   ///ついでにNameプロパティも変更
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static int NotesCount = 1;
        static Form Notes;   ///Form間での重複を避けるためStatic属性を付ける
        private void FormCreate_Click(object sender, EventArgs e)
        {
           Notes = new Note();
            Notes.Name = "Note_" + NotesCount;
            Notes.Show();
            NotesCount++;
          
        }
       



        /// <summary>
        /// 複数のFormについてプロパティの保存を行う
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormsPropatySave_Click(object sender, EventArgs e)
        {

             SL = new StickyList();
            //データリスト初期化



            SL.DataList = new List<StickyData>();
            //


            for (int i =0;  i < Application.OpenForms.Count   ; i++)
            {

                var SD = new StickyData();


                //  開かれているFormインスタンスを取得
                //各フォームのプロパティ情報を配列に格納
                SD.FileName = Application.OpenForms[i].Name + ".rtf";
                  SD.Height = Application.OpenForms[i].Height;
                SD.Width = Application.OpenForms[i].Width;
                SD.Top = Application.OpenForms[i].Top;
                SD.Left = Application.OpenForms[i].Left;
                SD.BackColor = Application.OpenForms[i].Controls["richTextBox1"].BackColor.Name;
  //子コントロールをnameプロパティを使ってアクセス       

                SL.DataList.Add(SD);
            }


        }

※Formのnameプロパティを”Note”に替えた。
  出力結果(成功)
   <?xml version="1.0" encoding="utf-8"?>
<StickyList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Sticky>
    <FileName>Note.rtf</FileName>
    <Width>415</Width>
    <Height>300</Height>
    <Top>26</Top>
    <Left>26</Left>
    <BackColor>Beige</BackColor>
  </Sticky>
  <Sticky>
    <FileName>Note_1.rtf</FileName>
    <Width>415</Width>
    <Height>300</Height>
    <Top>139</Top>
    <Left>482</Left>
    <BackColor>AliceBlue</BackColor>
  </Sticky>
  <Sticky>
    <FileName>Note_2.rtf</FileName>
    <Width>415</Width>
    <Height>300</Height>
    <Top>217</Top>
    <Left>1027</Left>
    <BackColor>CadetBlue</BackColor>
  </Sticky>
</StickyList>


 c - 1 保存したXMLの内容を読み込んでLoadする
  
  
関連記事
スポンサーサイト

 【C#】Fakesticky

0 Comments

Leave a comment