【WPF】自作カレンダー その3(年間カレンダー)
おはようございます。
自作カレンダーその3です。
今回は、ひとまず目標にしていた年間カレンダーを作成します。
動的に生成できるようにしたのが幸いして?割と簡単に実装することができました。
前回のプログラムはこちら。
スポンサーリンク
スタイルの変更
画面サイズ変更時に各月のカレンダーも一緒にサイズが変わるようにします。
StyleDic.xaml(抜粋)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <!-- グループ:通常--> <Style x:Key="gp-normal"TargetType="GroupBox" > <Setter Property="VerticalAlignment"Value="Stretch"/> <Setter Property="HorizontalAlignment"Value="Stretch"/> <Setter Property="Background"Value="#FFFFFFFF"/> <Setter Property="Foreground"Value="#FF777777"/> <Setter Property="Height"Value="Auto"/> <Setter Property="Width"Value="Auto"/> <Setter Property="Margin"Value="2,2,2,2"/> </Style> <!-- グリッド:画面リサイズ対応 --> <Style x:Key="grid-stretch"TargetType="Grid" > <Setter Property="VerticalAlignment"Value="Stretch"/> <Setter Property="HorizontalAlignment"Value="Stretch"/> <Setter Property="Height"Value="Auto"/> <Setter Property="Width"Value="Auto"/> </Style> <!-- グリッド:カレンダー格納用--> <Style x:Key="grid-calendar-container" TargetType="Grid" BasedOn="{StaticResourcegrid-stretch}"> <Setter Property="Background"Value="#FFFFFFFF"/> <Setter Property="Margin"Value="10,55,10,10"/> </Style> <!-- グリッド:カレンダー --> <Style x:Key="grid-calendar" TargetType="Grid" BasedOn="{StaticResourcegrid-stretch}"> <Setter Property="Background"Value="#FFFFFFFF"/> <Setter Property="Margin"Value="0,0,0,0"/> </Style> |
カレンダー格納グリッドのスタイル追加し、グループボックスとカレンダーグリッドの幅と高さを「Auto」、縦横位置を「Stretch」に変更。
画面の変更
こちらも、サイズ変更の対応と、年月ボックスを年ボックスに変更します。
MainWindow.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <Mah:MetroWindow x:Class="CalendarSample.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:CalendarSample" xmlns:Mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro" GlowBrush="{DynamicResource AccentColorBrush}" mc:Ignorable="d" WindowStartupLocation="CenterScreen" Title="カレンダーサンプル"Width="1024"Height="768"> <Window.Resources> <ResourceDictionary Source="/Style/StyleDic.xaml"/> </Window.Resources> <DockPanel > <Grid x:Name="MainContainer"Height="Auto"Width="Auto" > <Label x:Name="lbYear"Content="対象年:"HorizontalAlignment="Left"Margin="10,20,0,0"VerticalAlignment="Top" /> <ComboBox x:Name="cbYear"HorizontalAlignment="Left"Margin="61,20,0,0"VerticalAlignment="Top"Width="120"SelectionChanged="cbYear_SelectionChanged"/> <Label x:Name="lbDate"Content="選択された日付:"HorizontalAlignment="Left"Margin="222,20,0,0"VerticalAlignment="Top"/> <Label x:Name="lbSelectedDate"Content=""HorizontalAlignment="Left"Margin="333,20,0,0"VerticalAlignment="Top"/> <Grid x:Name="CalendarContainer"HorizontalAlignment="Stretch"VerticalAlignment="Stretch"Height="Auto"Margin="0,53,0,0"Width="Auto"/> </Grid> </DockPanel> </Mah:MetroWindow> |
全体を「DocPanel」で囲み、画面の枠組みとなるグリッドの幅と高さを「Auto」に、
カレンダー格納グリッドの幅と高さを「Auto」、縦横位置を「Strech」に変更します。
プログラム修正
新規クラス追加
年コンボボックス用のクラスを追加します。
YearInfo.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | usingSystem; usingSystem.Collections.Generic; usingSystem.IO; usingSystem.Linq; usingSystem.Text; namespaceCalendarSample { /// <summary> /// 年情報 /// </summary> publicclassYearInfo { /// <summary> /// コンストラクタ /// </summary> /// <param name="yearMonth"></param> publicYearInfo(Stringyear) { this.Year=year; this.YearWithKanji=year+"年"; } /// <summary> /// 年 /// </summary> publicStringYear{set;get;} /// <summary> /// 年(YYYY年) /// </summary> publicStringYearWithKanji{set;get;} } } |
月、日付情報クラスの修正
月情報クラスを年情報クラスの派生クラスに変更し、それに伴い日付情報クラスも変更します。
MonthInfo.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Text; usingSystem.Threading.Tasks; namespaceCalendarSample { /// <summary> /// 年月情報 /// </summary> publicclassMonthInfo:YearInfo { /// <summary> /// コンストラクタ /// </summary> /// <param name="yearMonth"></param> publicMonthInfo(Stringyear,Stringmonth):base(year) { this.Month=month; this.YearMonth=year+month; this.YearMonthWithKanji=year+"年"+month+"月"; } publicStringMonth{set;get;} /// <summary> /// 年月 /// </summary> publicStringYearMonth{set;get;} /// <summary> /// 年月(YYYY年MM月) /// </summary> publicStringYearMonthWithKanji{set;get;} } } |
DateInfo.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Text; usingSystem.Threading.Tasks; namespaceCalendarSample { /// <summary> /// 日付情報 /// </summary> publicclassDateInfo:MonthInfo { /// <summary> /// コンストラクタ /// </summary> /// <param name="yearMonth"></param> /// <param name="day"></param> publicDateInfo(Stringyear,Stringmonth, Stringday):base(year,month) { this.YearMonthDay=year+month+day; this.Date=newDateTime(int.Parse(Year),int.Parse(Month),int.Parse(day)); } publicDateTimeDate{set;get;} /// <summary> /// 年月日 /// </summary> publicStringYearMonthDay{set;get;} /// <summary> /// 年月日(YYYY年MM月DD日) /// </summary> publicStringgetYearMonthDayWithKanji() { returnString.Format("{0:yyyy年MM月dd日(ddd)}",Date); } /// <summary> /// 日を返します. /// </summary> /// <returns></returns> publicStringgetDay() { if(String.IsNullOrEmpty(YearMonthDay))return""; returnYearMonthDay.Substring(6,2); } } } |
コードビハインドの修正
次の変更を実施
- 年間カレンダー作成メソッドの追加
- グリッドのマトリクス設定メソッドの追加
- 年月コンボ選択変更イベントを年コンボ選択変更イベントメソッドに変更
- 初期化処理にて、年コンボ用の項目を生成、セットした後に当年のカレンダーを作成して画面にセットする
MainWindo.xaml.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Text; usingSystem.Threading.Tasks; usingSystem.Windows; usingSystem.Windows.Controls; usingSystem.Windows.Data; usingSystem.Windows.Documents; usingSystem.Windows.Input; usingSystem.Windows.Media; usingSystem.Windows.Media.Imaging; usingSystem.Windows.Navigation; usingSystem.Windows.Shapes; usingMahApps.Metro.Controls; namespaceCalendarSample { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> publicpartial classMainWindow:MetroWindow { privateRectangle selectedRec; privateStyle selectedRecStyle; publicMainWindow() { InitializeComponent(); // 前月から6カ月分のリストを作成し、当月を選択させる List<YearInfo>list=newList<YearInfo>(); DateTime now=DateTime.Now; DateTime dt=now.AddYears(-1); for(inti=0;i<6;i++) { list.Add(newYearInfo(String.Format("{0:yyyy}",dt))); dt=dt.AddYears(1); } this.cbYear.ItemsSource=list; this.cbYear.DisplayMemberPath="YearWithKanji"; this.cbYear.SelectedIndex=1; setGridMatrix(CalendarContainer,3,4); // 年間カレンダー作成 createYearsCalendar(this.cbYear.SelectedItem asYearInfo); } /// <summary> /// 年コンボの選択変更イベントハンドラー. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> privatevoidcbYear_SelectionChanged(objectsender,SelectionChangedEventArgse) { // 年間カレンダー作成 createYearsCalendar(this.cbYear.SelectedItem asYearInfo); } /// <summary> /// 年間カレンダーを作成. /// </summary> /// <param name="yearInfo"></param> privatevoidcreateYearsCalendar(YearInfo yearInfo) { CalendarContainer.Children.Clear(); for(inti=0;i<12;i++) { // 横位置 intx=i%4; // 縦位置 inty=i/4; // カレンダー作成 Stringyear=(this.cbYear.SelectedItem asYearInfo).Year; MonthInfo mi=newMonthInfo(year,String.Format("{0:00}",(i+1))); GroupBox gb=createCalendar(mi); CalendarContainer.Children.Add(gb); gb.SetValue(Grid.ColumnProperty,x); gb.SetValue(Grid.RowProperty,y); } } /// <summary> /// 指定された年月のカレンダーを作成. /// </summary> /// <param name="monthInfo"></param> privateGroupBox createCalendar(MonthInfo monthInfo){ // グループボックス GroupBox calendarGroup=newGroupBox(); calendarGroup.Header=monthInfo.YearMonthWithKanji; calendarGroup.Style=FindResource("gp-normal")asStyle; // グリッド Grid calendarGrid=newGrid(); setGridMatrix(calendarGrid,7,7); calendarGrid.Style=FindResource("grid-calendar")asStyle; // 1行目のみ高さ固定とする calendarGrid.RowDefinitions.First().Height=newGridLength(20); // グリッド枠線 Rectangle border=newRectangle(); border.Style=FindResource("rec-border")asStyle; calendarGrid.Children.Add(border); for(intcol=0;col<7;col++) { Rectangle week=newRectangle(); week.Style=(col==6)?FindResource("rec-week-sat")asStyle:FindResource("rec-week")asStyle; week.SetValue(Grid.ColumnProperty,col); calendarGrid.Children.Add(week); Label lbWeek=newLabel(); lbWeek.Style=FindResource("lb-week")asStyle; lbWeek.Content=("日月火水木金土").Substring(col,1); lbWeek.SetValue(Grid.ColumnProperty,col); calendarGrid.Children.Add(lbWeek); } // ヘッダ行下線 Rectangle underlining=newRectangle(); underlining.Style=FindResource("rec-underlining")asStyle; calendarGrid.Children.Add(underlining); // グループボックスにグリッドを追加 calendarGroup.Content=calendarGrid; //CalendarContainer.Children.Add(calendarGroup); // 当月の月初を取得 varfirstDate=newDateTime(int.Parse(monthInfo.Year),int.Parse(monthInfo.Month),1); // 曜日番号の取得 intdayOfWeek=(int)firstDate.DayOfWeek; // 月末を取得 intlastDay=firstDate.AddMonths(1).AddDays(-1).Day; // 1日から月末までを走査 for(intday=1;day<=lastDay;day++) { // セル位置 intindex=(day-1)+dayOfWeek; // 横位置 intx=index%7; // 縦位置 inty=index/7; // テキストブロックを生成してグリッドに追加 vartb=newTextBlock(); tb.Text=String.Format("{0}",day); // 土日は文字色を変更する if(x==0) { tb.Style=FindResource("txb-date-sun")asStyle; } elseif(x==6) { tb.Style=FindResource("txb-date-sat")asStyle; } else { tb.Style=FindResource("txb-date")asStyle; } calendarGrid.Children.Add(tb); tb.SetValue(Grid.ColumnProperty,x); tb.SetValue(Grid.RowProperty,y+1); // 四角形を生成してグリッドに追加 // セルの枠線などを表示し、イベントをハンドリングする用 varrec=newRectangle(); DateInfo dt=newDateInfo(monthInfo.Year,monthInfo.Month,String.Format("{0:00}",day)); rec.DataContext=dt; // 枠線を調整 rec.Style=(x==6)?FindResource("rec-date-sat")asStyle:FindResource("rec-date")asStyle; // イベント設定 rec.MouseLeftButtonDown+=date_MouseLeftButtonDown; calendarGrid.Children.Add(rec); rec.SetValue(Grid.ColumnProperty,x); rec.SetValue(Grid.RowProperty,y+1); } returncalendarGroup; } /// <summary> /// グリッドのマトリックスのひな形を設定 /// </summary> /// <param name="grid"></param> /// <param name="rowCount"></param> /// <param name="columnCount"></param> privatevoidsetGridMatrix(Grid grid,introwCount,intcolumnCount) { // 行のセット for(inti=0;i<rowCount;i++) { grid.RowDefinitions.Add(newRowDefinition(){Height=newGridLength(1,GridUnitType.Star)}); } // 列のセット for(inti=0;i<columnCount;i++) { grid.ColumnDefinitions.Add(newColumnDefinition(){Width=newGridLength(1,GridUnitType.Star)}); } } /// <summary> /// セル(日)をクリックした際のイベントハンドラ. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> privatevoiddate_MouseLeftButtonDown(objectsender,MouseButtonEventArgse) { // 既に選択されたセルがある場合はスタイルを戻す if(selectedRec!=null) { selectedRec.Style=selectedRecStyle; } // 選択されたセルの取得 Rectangle rec=sender asRectangle; // 選択セルの保持 selectedRec=rec; selectedRecStyle=rec.Style; // 選択時のスタイルに変更 rec.Style=FindResource("rec-date-selected")asStyle; // ラベルに日付をセット lbSelectedDate.Content=(rec.DataContext asDateInfo).getYearMonthDayWithKanji(); } } } |
起動してみる
年月の時と同様、6年分のリストを作成しデフォルト表示を当年としました。
年を変更した際の表示です。
セルを選択するとちゃんと日付が表示されます。
少し分かりにくいですが、画面サイズを縮小した際の表示です。
こちらは分かりやすいですかね。
まとめ
ひとまず目標のところまで出来たので一旦完了とします。
(また何か思いついたら追加で実装するかもしれません。)
ではでは。
ディスカッション
コメント一覧
まだ、コメントがありません