2009年11月12日木曜日

今日作成したサイト、ソースコード。

掲示板

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class Chap7_keiji_main : System.Web.UI.Page
{
    const string DataFolderURL = "~/Chap7/Data/";
    const string SubjectDBFileName = "SubjectDB.xml";
    const string SubjectDBSchemaName = "SubjectDB.xsd";
    const string ReplyDBFileName = "ReplyDB";

    string DataFolder;

    DataSet SubjectDS = new DataSet();
    DataSet ReplyDS = new DataSet();
    DataTable SubjectTable, ReplyTable;

    // ページを読み込んだ時の処理。
    protected void Page_Load(object sender, EventArgs e)
    {
        int id;

        DataFolder = Server.MapPath(DataFolderURL);

        // テーマ用のDBを読み込んで表示する。
        SubjectDS.ReadXmlSchema(DataFolder + SubjectDBSchemaName);
        SubjectDS.ReadXml(DataFolder + SubjectDBFileName);
        SubjectTable = SubjectDS.Tables["Subject"];
        GridView_Subject.DataSource = SubjectTable;
        GridView_Subject.DataBind();

        if (!IsPostBack)
        {
            // セッションオブジェクトでテーマが指定されている場合にはその番号を表示する。
            // 上記指定が無い場合は最新のテーマを表示する。
            if (Session["SubjectID"] != null)
            {
                id = (int)Session["SubjectID"];
            }
            else
            {
                id = (int)SubjectTable.Rows[SubjectTable.Rows.Count - 1]["ID"];
                Session["SubjectID"] = id;
            }
            DisplayArticle(id);
        }
    }

    // [更新] ボタンが押された時の処理。
    protected void Button_Refresh_Click(object sender, EventArgs e)
    {
        if (Literal_SubjectID.Text != "")
            DisplayArticle(Convert.ToInt32(Literal_SubjectID.Text));
        else
            DisplayArticle(-1);

        // 入力用のパネルが表示されている場合があるので非表示にする。
        Panel_SubjectAdd.Visible = false;
        Panel_ReplyAdd.Visible = false;
    }

    // [新しいテーマ] ボタンが押された時の処理。
    protected void Button_NewSubject_Click(object sender, EventArgs e)
    {
        // 新規テーマ入力用のパネルを表示する。
        Panel_SubjectAdd.Visible = true;
        Panel_ReplyAdd.Visible = false;
        S_Error.Text = "";
        S_Title_Input.Focus();
    }

    // [返事を書く] ボタンが押された時の処理。
    protected void Button_NewReply_Click(object sender, EventArgs e)
    {
        // 返信入力用のパネルを表示する。
        Panel_SubjectAdd.Visible = false;
        Panel_ReplyAdd.Visible = true;
        R_Error.Text = "";
        R_Text_Input.Focus();
    }

    // 新しいテーマ用の[登録] ボタンが押された時の処理。
    protected void S_Button_Add_Click(object sender, EventArgs e)
    {
        DataRow row;
        int id;

        if (S_Title_Input.Text == "")
        {
            S_Error.Text = "タイトルを入力してください。";
            return;
        }

        row = SubjectTable.NewRow();

        if (SubjectTable.Rows.Count != 0)
            id = (int)SubjectTable.Rows[SubjectTable.Rows.Count - 1]["ID"] + 1;
        else
            id = 1;
        row["ID"] = id;
        row["Date"] = DateTime.Now.ToString();
        row["Person"] = Server.HtmlEncode(S_Person_Input.Text);
        row["Title"] = Server.HtmlEncode(S_Title_Input.Text);
        row["Text"] = Server.HtmlEncode(S_Text_Input.Text);
        row["ReplyNum"] = 0;

        SubjectTable.Rows.Add(row);

        try
        {
            SubjectDS.WriteXml(DataFolder + SubjectDBFileName);

            Session["SubjectID"] = id;

            Response.Redirect("added.htm");
        }
        catch
        {
            S_Error.Text = "SubjectDBファイルの更新時にエラーが発生しました。";
        }
    }

    // 返信用の[登録] ボタンが押された時の処理。
    protected void R_Button_Add_Click(object sender, EventArgs e)
    {
        int id;
        DataRow row;

        // テーマが選択されていないか、存在しない場合のエラー処理。
        if (Literal_SubjectID.Text == "")
        {
            R_Error.Text = "返信するテーマを先に選択してください。";
            return;
        }
        if (!SubjectTable.Rows.Contains(Convert.ToInt32(Literal_SubjectID.Text)))
        {
            R_Error.Text = "このテーマは削除されました。";
            DisplayArticle(-1);
            return;
        }

        // 返信用のDBをロードする。
        try
        {
            ReplyDS.Clear();
            ReplyDS.ReadXml(DataFolder + ReplyDBFileName + Literal_SubjectID.Text + ".xml");
            ReplyTable = ReplyDS.Tables["Reply"];
        }
        catch
        {
            // 返信用のDBが無いので作成する。
            ReplyDS.DataSetName = "Replies";
            ReplyTable = ReplyDS.Tables.Add("Reply");
            ReplyTable.Columns.Add("ID", Type.GetType("System.Int32"));
            ReplyTable.Columns.Add("Date");
            ReplyTable.Columns.Add("Person");
            ReplyTable.Columns.Add("Text");
            ReplyTable.PrimaryKey = new DataColumn[] { ReplyTable.Columns["ID"] };
        }
        // 返信用DBに新しい行を追加する。
        row = ReplyTable.NewRow();

        if (ReplyTable.Rows.Count != 0)
            id = (int)ReplyTable.Rows[ReplyTable.Rows.Count - 1]["ID"] + 1;
        else
            id = 1;
        row["ID"] = id;
        row["Date"] = DateTime.Now.ToString();
        row["Person"] = Server.HtmlEncode(R_Person_Input.Text);
        row["Text"] = Server.HtmlEncode(R_Text_Input.Text);
        ReplyTable.Rows.Add(row);

        // 返信DBをXMLファイルにスキーマ情報と共に書き出す。
        try
        {
            ReplyDS.WriteXml(DataFolder + ReplyDBFileName + Literal_SubjectID.Text + ".xml", XmlWriteMode.WriteSchema);
        }
        catch
        {
            R_Error.Text = "ReplyDBファイルの更新時にエラーが発生しました。";
            return;
        }

        // テーマDBの返信数を増やす。
        row = SubjectTable.Rows.Find(Literal_SubjectID.Text);
        row["ReplyNum"] = (int)row["ReplyNum"] + 1;

        // テーマDBのデータを更新する。
        try
        {
            SubjectDS.WriteXml(DataFolder + SubjectDBFileName);

            // 現在のテーマの番号をセッション オブジェクトに保存する。
            Session["SubjectID"] = Convert.ToInt32(Literal_SubjectID.Text);

            // 登録完了画面にリダイレクトする。
            Response.Redirect("added.htm");
        }
        catch
        {
            R_Error.Text = "SubjectDBファイルの更新時にエラーが発生しました。";
        }
    }

    // DataList_Reply の行にデータをバインドした時の処理。
    protected void DataList_Reply_ItemDataBound(object sender, DataListItemEventArgs e)
    {
        // 改行コードを <br /> タグに置き換える。
        if (e.Item.ItemType == ListItemType.Item ||
            e.Item.ItemType == ListItemType.AlternatingItem)
        {
            Literal R_Text = (Literal)e.Item.FindControl("R_Text");
            R_Text.Text = R_Text.Text.Replace("\r\n", "<br />");
        }
    }

    // 引数で指定されたテーマを選択し、対応する記事を表示する。
    protected void DisplayArticle(int id)
    {
        DataRow row;

        // 存在しないテーマを指定された場合の処理。
        if (!SubjectTable.Rows.Contains(id))
        {
            // 記事の表示をクリアする
            Literal_SubjectID.Text = "";
            Label_Person.Text = "名前";
            Label_Date.Text = "時刻";
            Literal_SubjectText.Text = "";
            DataList_Reply.DataSource = null;
            DataList_Reply.DataBind();
            GridView_Subject.SelectedIndex = -1;
            return;
        }

        row = SubjectTable.Rows.Find(id);
        GridView_Subject.SelectedIndex = SubjectTable.Rows.IndexOf(row);

        // 選択されたテーマのタイトル、内容、投稿者、日付を表示する。
        Literal_SubjectID.Text = row["ID"].ToString();
        Label_Person.Text = (string)row["Person"];
        Label_Date.Text = (string)row["Date"];
        Literal_SubjectText.Text = ((string)row["Text"]).Replace("\r\n", "<br />");

        // このテーマに対応する返信DBファイルを読み込む。
        try
        {
            ReplyDS.Clear();
            ReplyDS.ReadXml(DataFolder + ReplyDBFileName + id + ".xml");

            // このテーマの返信を一覧表示する。
            DataList_Reply.DataSource = ReplyDS.Tables["Reply"];
            DataList_Reply.DataBind();
        }
        catch
        {
            // このテーマの返信DBファイルが無いので、返信欄をクリアする。
            DataList_Reply.DataSource = null;
            DataList_Reply.DataBind();
        }
    }
    protected void GridView_Subject_RowCommand(object sender, GridViewCommandEventArgs e)
    {
        int id, indexGV;

        if (e.CommandName == "Select")
        {
            indexGV = Convert.ToInt32(e.CommandArgument);
            id = Convert.ToInt32(GridView_Subject.Rows[indexGV].Cells[0].Text);
            DisplayArticle(id);
            Session["SubjectID"] = id;
        }

        Panel_SubjectAdd.Visible = false;
        Panel_ReplyAdd.Visible = false;
    }
}

せっかく作成したので、出来上がっているかどうか自分自身で試してみました。新しいテーマの作成、投稿、返事としてみたのですが成功しているみたいで、ちゃんと表示された瞬間とても嬉しかったです。掲示板管理画面の編集も記事の削除等しっかり動きました。大満足です。

上記はVMware Fusion 3上のWindows XP Home EditionのInternet Explorer 8で試してみたのですが、続いてMac OS X Snow LeopardのSafari 4で試してみたら、表示が少し崩れました。さらにIE8の互換表示設定で従来のブラウザ向け(Internet Explorer 7?、6?)で表示してみたらまたさらに表示が崩れてはいませんが違いました。しかし、どちらも機能自体はInternet Explorer 8と同様にしっかり動いたので、とりあえずは良しとします。

いずれはどのブラウザ(とはいっても世界中のすべてのブラウザではなくIE(Windows Mobile含む),Firefox,Safari(iPhone含む),Chrome,そしてOperaなどなど)でも綺麗に表示させることができるようになりたいなあと思ったりしています。さらに成長したら、モバイル専用のサイト作成にも挑戦してみたいなあと思ったりもしています。

プログラミング チャレンジ スクエアのプログラミングはこれで終了のようです。次回は少しサイトのデザインについて学ぶことができるようなので、また次回のプログラミングの学習がわくわく楽しみな今日この頃です。

0 コメント:

コメントを投稿