質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.13%

Visual studio 2015 自作カレンダー

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 12K+

niko2

score 15

前提・実現したいこと

Visual Studio 2015 でC#をシステムを開発しています。

現在、日々のトレーニングなどを記録するシステムのカレンダー部分を作っています。

カレンダーを自作で作っているのですが、
仕様として、画像のように
プルダウンで年、月を選ぶとその年月のカレンダーがラベルで表示されるようにしようしています。(左上のカレンダーは題名、右上は更新日時、最終更新者となっています。)

日付をラベルで作る意図としては、そのラベルをクリックするとその日の予定一覧画面に飛べるようにするためです。

発生している問題・エラーメッセージ

しかし、プルダウンで年月を選ぶとその年月のカレンダーを表示させる方法がわかりません。
実現する方法を教えていただけないでしょうか?

該当のソースコード

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Calendar : Form
    {
        public Calendar()
        {
            InitializeComponent();
        }



        private void button1_Click(object sender, EventArgs e)/戻るボタンの処理(今回の質問に関係なし)
        {
            Windows1.Menu menu = new Windows1.Menu();
            menu.Show();
            Close();
        }

        private void label13_Click(object sender, EventArgs e)/日付ラベルをクリックするとその日の予定画面を開く
        {
            CalendarDetails.CalendarDetails calendardetails = new CalendarDetails.CalendarDetails();
            calendardetails.Show();
            Close();
        }
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

そういうことですか、私もちょっと探してみましたが大きくする方法は
ほかの誰かが作ったコントロール使う以外にはあまりなさそうな感じでしたね。

自作するとなると以下のようなことを事が少し問題になってくるかと思われます。

  1. コンボボックス(年の方)はどれくらいの範囲で入れるか(現在±100年等)
  2. ラベルをすでに置いてて、日付だけ変えてるのであれば、1日が日曜だった場合5行じゃ足りない

適当に作ってそれっぽく動いたのが以下のコードになります。

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) {
    //月が選択された
    month = (int)comboBox1.SelectedItem;
    setDate();
}

private void comboBox2_SelectedIndexChanged(object sender, EventArgs e) {
    //年が選択された
    year = (int)comboBox2.SelectedItem;
    setDate();
}
private void setDate() {
    var dFirst = new DateTime(year, month, 1);//選択された年月の1日
    var dLast = dFirst.AddMonths(1).AddDays(-1);//選択された年月の最終日
    var bdLast = dFirst.AddDays(-1);//先月の最終日
    //numは1日をどのラベルからはじめるか決める変数
    //日付に使用するラベル名はlabel8~label44
    int num = 0;//月曜の場合8でそれ以降順に1づつ増える
    if(dFirst.DayOfWeek == DayOfWeek.Monday) {
        num = 8;//月曜はlabel8
    } else if(dFirst.DayOfWeek == DayOfWeek.Tuesday) {
        num = 9;//火曜はlabel9
    } else if(dFirst.DayOfWeek == DayOfWeek.Wednesday) {
        num = 10;//水曜はlabel10
    } else if(dFirst.DayOfWeek == DayOfWeek.Thursday) {
        num = 11;//木曜はlabel11
    } else if(dFirst.DayOfWeek == DayOfWeek.Friday) {
        num = 12;//金曜はlabel12
    } else if(dFirst.DayOfWeek == DayOfWeek.Saturday) {
        num = 13;//土曜はlabel13
    } else if(dFirst.DayOfWeek == DayOfWeek.Sunday) {
        num = 14;//日曜はlabel4
    }
    //label8~label49(6行分)全部設定
    for(int i = 8; i <= 49; i++) {
        var d = i - num;//1日より何日前か(後か)
        this.Controls["label" + i].Text = (dFirst.AddDays(d).Day).ToString();
        if(i < num || d >= dLast.Day) {
            //選択月の前の月の最後の方と次の月の最初はグレー
            this.Controls["label" + i].ForeColor = Color.Gray;
        } else {
            //選択月は黒
            this.Controls["label" + i].ForeColor = Color.Black;
        }
    }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/11/19 22:39

    私自身がプログラミングが初心者に毛が生えたレベルのため、知識と理解力が乏しく、
    頂いたソースを実行してみたところうまくいきませんでした。

    テストように新たにフォームを作成し、comboBox1、comboBox2、label1~43を作成し、頂いたソースを実行してみました。
    しかし、そのままlabel1~43が表示されるだけでcomboBoxに数値を入力してみても反応ありませんでした。labelのテキストも変わっていない状況です。

    疑問点があるのですが
    ・頂いたソースを実行するにあたり、month,yearをフォームにint型で定義しましたがあってますでしょうか。
    ・private void setDate() を自分でソースを入力しましたが、labelなどのように、どこかをクリックして自動的にprivate void setDate() {}をつくらないといけないのでしょうか。

    初心者すぎる質問かもしれませんが、何卒回答していただけると幸いです。

    キャンセル

  • 2016/11/19 22:58

    疑問点について:
    ・int型でのmonthとyearの定義はその通りです。
    ・private void setData()関数はForm1.csに手で書き込みました。

    以下のコードでcomboBox1、comboBox2、label1~43を作成+以下のコードをコピペで動くと思います。
    ```C#
    public partial class Form1 : Form {
    int year = DateTime.Now.Year;
    int month = DateTime.Now.Month;
    public Form1() {
    InitializeComponent();

    for(int i = 1; i <= 12; i++)
    comboBox1.Items.Add(i);
    for(int i = year - 100; i <= year + 100; i++)
    comboBox2.Items.Add(i);
    comboBox1.SelectedItem = month;
    comboBox2.SelectedItem = year;
    comboBox1.SelectedIndexChanged += comboBox1_SelectedIndexChanged;
    comboBox2.SelectedIndexChanged += comboBox2_SelectedIndexChanged;
    }

    private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) {
    //年が選択された
    month = (int)comboBox1.SelectedItem;
    setDate();
    }

    private void comboBox2_SelectedIndexChanged(object sender, EventArgs e) {
    //月が選択された
    year = (int)comboBox2.SelectedItem;
    setDate();
    }

    private void setDate() {
    var dFirst = new DateTime(year, month, 1);//選択された年月の1日
    var dLast = dFirst.AddMonths(1).AddDays(-1);//選択された年月の最終日
    var bdLast = dFirst.AddDays(-1);//先月の最終日
    //numは1日をどのラベルからはじめるか決める変数
    //日付に使用するラベル名はlabel8~label44
    int num = 0;//月曜の場合1でそれ以降順に1づつ増える
    if(dFirst.DayOfWeek == DayOfWeek.Monday) {
    num = 8;//月曜はlabel8
    } else if(dFirst.DayOfWeek == DayOfWeek.Tuesday) {
    num = 9;//火曜はlabel9
    } else if(dFirst.DayOfWeek == DayOfWeek.Wednesday) {
    num = 10;//水曜はlabel10
    } else if(dFirst.DayOfWeek == DayOfWeek.Thursday) {
    num = 11;//木曜はlabel11
    } else if(dFirst.DayOfWeek == DayOfWeek.Friday) {
    num = 12;//金曜はlabel12
    } else if(dFirst.DayOfWeek == DayOfWeek.Saturday) {
    num = 13;//土曜はlabel13
    } else if(dFirst.DayOfWeek == DayOfWeek.Sunday) {
    num = 14;//日曜はlabel8
    }
    //label8~label49全部設定
    for(int i = 8; i <= 49; i++) {
    var d = i - num;//1日より何日前か(後か)
    this.Controls["label" + i].Text = (dFirst.AddDays(d).Day).ToString();
    if(i < num || d >= dLast.Day) {
    //選択月の前の月の最後の方
    this.Controls["label" + i].ForeColor = Color.Gray;
    } else {
    //選択月
    this.Controls["label" + i].ForeColor = Color.Black;
    }
    }
    }
    }
    ```

    キャンセル

  • 2016/11/19 23:01

    すいません、訂正で、label1~49を作成です。(label1~7は月~日の曜日用です)

    キャンセル

  • 2016/11/21 15:31

    丁寧な回答、ありがとうございます。
    無事実行できました。
    ベストアンサーに選ばせていただきました。
    ありがとうございます。

    キャンセル

0

質問で返してすいませんが、MonthCalendarコントロールを使用しない理由が何かありますか?
年/月の選択や曜日の設定等は全く考える事無く必要な処理を実装できそうな気がしますが。

//monthCalendar1.MaxSelectionCount=1;

private void monthCalendar1_DateSelected(object sender, DateRangeEventArgs e) {
    DateTime selected = monthCalendar1.SelectionStart;//選択した日付
    //日付を選択したときにする処理
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/11/18 21:53

    HeyHeyHoさん

    回答ありがとうございます。

    MonthCalendarコントロールを使わない理由としては、画面のサイズに大きさを変更出来ないからです。

    http://blog.hiros-dot.net/?page_id=3495 などを参考にしてみましたが、このページではWindowsFormを使用した場合については述べられていなかったため、大きさを変更する方法が見つかりませんでした。

    そのため、自作でカレンダーを作る以外方法がないのではないかと考え、今に至ります。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.13%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる