tag:crieit.net,2005:https://crieit.net/magazines/doraxdorax/WPF%E8%87%AA%E4%BD%9C%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%80%E3%83%BC/feed
WPFで自作のカレンダーを作ってみるの投稿 - Crieit
Crieitで連載「WPFで自作のカレンダーを作ってみる」の最近の投稿
2019-06-20T14:45:25+09:00
https://crieit.net/magazines/doraxdorax/WPF%E8%87%AA%E4%BD%9C%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%80%E3%83%BC/feed
tag:crieit.net,2005:PublicArticle/15133
2019-06-20T14:45:25+09:00
2019-06-20T14:45:25+09:00
https://crieit.net/posts/WPF-5d0b1d755145b
【WPF】自作カレンダー その3(年間カレンダー)
<p>おはようございます。</p>
<p>自作カレンダーその3です。<br />
今回は、ひとまず目標にしていた年間カレンダーを作成します。</p>
<p>動的に生成できるようにしたのが幸いして?割と簡単に実装することができました。</p>
<p>前回のプログラムはこちら。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/10/16/post-2779/" target="_blank" rel="noopener noreferrer" data-blogcard="1">【WPF】自作カレンダー その2(動的生成)</a></p>
<h2 id="スタイルの変更"><a href="#%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%81%AE%E5%A4%89%E6%9B%B4">スタイルの変更</a></h2>
<p>画面サイズ変更時に各月のカレンダーも一緒にサイズが変わるようにします。</p>
<p>StyleDic.xaml(抜粋)</p>
<pre><code> <!-- グループ:通常-->
<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="{StaticResource grid-stretch}">
<Setter Property="Background" Value="#FFFFFFFF" />
<Setter Property="Margin" Value="10, 55, 10, 10" />
</Style>
<!-- グリッド:カレンダー -->
<Style x:Key="grid-calendar" TargetType="Grid" BasedOn="{StaticResource grid-stretch}">
<Setter Property="Background" Value="#FFFFFFFF" />
<Setter Property="Margin" Value="0, 0, 0, 0" />
</Style>
</code></pre>
<p>カレンダー格納グリッドのスタイル追加し、グループボックスとカレンダーグリッドの幅と高さを「Auto」、縦横位置を「Stretch」に変更。</p>
<h2 id="画面の変更"><a href="#%E7%94%BB%E9%9D%A2%E3%81%AE%E5%A4%89%E6%9B%B4">画面の変更</a></h2>
<p>こちらも、サイズ変更の対応と、年月ボックスを年ボックスに変更します。</p>
<p>MainWindow.xaml</p>
<pre><code><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>
</code></pre>
<p>全体を「DocPanel」で囲み、画面の枠組みとなるグリッドの幅と高さを「Auto」に、<br />
カレンダー格納グリッドの幅と高さを「Auto」、縦横位置を「Strech」に変更します。</p>
<h2 id="プログラム修正"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E4%BF%AE%E6%AD%A3">プログラム修正</a></h2>
<h3 id="新規クラス追加"><a href="#%E6%96%B0%E8%A6%8F%E3%82%AF%E3%83%A9%E3%82%B9%E8%BF%BD%E5%8A%A0">新規クラス追加</a></h3>
<p>年コンボボックス用のクラスを追加します。</p>
<p>YearInfo.cs</p>
<pre><code> using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace CalendarSample
{
/// <summary>
/// 年情報
/// </summary>
public class YearInfo
{
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="yearMonth"></param>
public YearInfo(String year)
{
this.Year = year;
this.YearWithKanji = year + "年";
}
/// <summary>
/// 年
/// </summary>
public String Year { set; get; }
/// <summary>
/// 年(YYYY年)
/// </summary>
public String YearWithKanji { set; get; }
}
}
</code></pre>
<p> </p>
<h3 id="月、日付情報クラスの修正"><a href="#%E6%9C%88%E3%80%81%E6%97%A5%E4%BB%98%E6%83%85%E5%A0%B1%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%AE%E4%BF%AE%E6%AD%A3">月、日付情報クラスの修正</a></h3>
<p>月情報クラスを年情報クラスの派生クラスに変更し、それに伴い日付情報クラスも変更します。</p>
<p>MonthInfo.cs</p>
<pre><code> using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CalendarSample
{
/// <summary>
/// 年月情報
/// </summary>
public class MonthInfo : YearInfo
{
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="yearMonth"></param>
public MonthInfo(String year, String month) : base(year)
{
this.Month = month;
this.YearMonth = year + month;
this.YearMonthWithKanji = year + "年" + month + "月";
}
public String Month { set; get; }
/// <summary>
/// 年月
/// </summary>
public String YearMonth { set; get; }
/// <summary>
/// 年月(YYYY年MM月)
/// </summary>
public String YearMonthWithKanji { set; get; }
}
}
</code></pre>
<p>DateInfo.cs</p>
<pre><code> using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CalendarSample
{
/// <summary>
/// 日付情報
/// </summary>
public class DateInfo : MonthInfo
{
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="yearMonth"></param>
/// <param name="day"></param>
public DateInfo(String year, String month, String day) : base(year, month)
{
this.YearMonthDay = year+ month + day;
this.Date = new DateTime(int.Parse(Year), int.Parse(Month), int.Parse(day));
}
public DateTime Date { set; get; }
/// <summary>
/// 年月日
/// </summary>
public String YearMonthDay { set; get; }
/// <summary>
/// 年月日(YYYY年MM月DD日)
/// </summary>
public String getYearMonthDayWithKanji()
{
return String.Format("{0:yyyy年MM月dd日(ddd)}", Date);
}
/// <summary>
/// 日を返します.
/// </summary>
/// <returns></returns>
public String getDay()
{
if (String.IsNullOrEmpty(YearMonthDay)) return "";
return YearMonthDay.Substring(6, 2);
}
}
}
</code></pre>
<h3 id="コードビハインドの修正"><a href="#%E3%82%B3%E3%83%BC%E3%83%89%E3%83%93%E3%83%8F%E3%82%A4%E3%83%B3%E3%83%89%E3%81%AE%E4%BF%AE%E6%AD%A3">コードビハインドの修正</a></h3>
<p>次の変更を実施</p>
<pre><code>年間カレンダー作成メソッドの追加
グリッドのマトリクス設定メソッドの追加
年月コンボ選択変更イベントを年コンボ選択変更イベントメソッドに変更
初期化処理にて、年コンボ用の項目を生成、セットした後に当年のカレンダーを作成して画面にセットする
</code></pre>
<p>MainWindo.xaml.cs</p>
<pre><code> using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using MahApps.Metro.Controls;
namespace CalendarSample
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : MetroWindow
{
private Rectangle selectedRec;
private Style selectedRecStyle;
public MainWindow()
{
InitializeComponent();
// 前月から6カ月分のリストを作成し、当月を選択させる
List<YearInfo> list = new List<YearInfo>();
DateTime now = DateTime.Now;
DateTime dt = now.AddYears(-1);
for (int i = 0; i < 6; i++ )
{
list.Add(new YearInfo(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 as YearInfo);
}
/// <summary>
/// 年コンボの選択変更イベントハンドラー.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void cbYear_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// 年間カレンダー作成
createYearsCalendar(this.cbYear.SelectedItem as YearInfo);
}
/// <summary>
/// 年間カレンダーを作成.
/// </summary>
/// <param name="yearInfo"></param>
private void createYearsCalendar(YearInfo yearInfo)
{
CalendarContainer.Children.Clear();
for (int i = 0; i < 12; i++)
{
// 横位置
int x = i % 4;
// 縦位置
int y = i / 4;
// カレンダー作成
String year = (this.cbYear.SelectedItem as YearInfo).Year;
MonthInfo mi = new MonthInfo(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>
private GroupBox createCalendar(MonthInfo monthInfo) {
// グループボックス
GroupBox calendarGroup = new GroupBox();
calendarGroup.Header = monthInfo.YearMonthWithKanji;
calendarGroup.Style = FindResource("gp-normal") as Style;
// グリッド
Grid calendarGrid = new Grid();
setGridMatrix(calendarGrid, 7, 7);
calendarGrid.Style = FindResource("grid-calendar") as Style;
// 1行目のみ高さ固定とする
calendarGrid.RowDefinitions.First().Height = new GridLength(20);
// グリッド枠線
Rectangle border = new Rectangle();
border.Style = FindResource("rec-border") as Style;
calendarGrid.Children.Add(border);
for (int col = 0; col < 7; col++)
{
Rectangle week = new Rectangle();
week.Style = (col == 6) ? FindResource("rec-week-sat") as Style : FindResource("rec-week") as Style;
week.SetValue(Grid.ColumnProperty, col);
calendarGrid.Children.Add(week);
Label lbWeek = new Label();
lbWeek.Style = FindResource("lb-week") as Style;
lbWeek.Content = ("日月火水木金土").Substring(col, 1);
lbWeek.SetValue(Grid.ColumnProperty, col);
calendarGrid.Children.Add(lbWeek);
}
// ヘッダ行下線
Rectangle underlining = new Rectangle();
underlining.Style = FindResource("rec-underlining") as Style;
calendarGrid.Children.Add(underlining);
// グループボックスにグリッドを追加
calendarGroup.Content = calendarGrid;
//CalendarContainer.Children.Add(calendarGroup);
// 当月の月初を取得
var firstDate = new DateTime(int.Parse(monthInfo.Year), int.Parse(monthInfo.Month), 1);
// 曜日番号の取得
int dayOfWeek = (int)firstDate.DayOfWeek;
// 月末を取得
int lastDay = firstDate.AddMonths(1).AddDays(-1).Day;
// 1日から月末までを走査
for (int day = 1; day <= lastDay; day++)
{
// セル位置
int index = (day - 1) + dayOfWeek;
// 横位置
int x = index % 7;
// 縦位置
int y = index / 7;
// テキストブロックを生成してグリッドに追加
var tb = new TextBlock();
tb.Text = String.Format("{0}", day);
// 土日は文字色を変更する
if (x == 0)
{
tb.Style = FindResource("txb-date-sun") as Style;
}
else if (x == 6)
{
tb.Style = FindResource("txb-date-sat") as Style;
}
else
{
tb.Style = FindResource("txb-date") as Style;
}
calendarGrid.Children.Add(tb);
tb.SetValue(Grid.ColumnProperty, x);
tb.SetValue(Grid.RowProperty, y + 1);
// 四角形を生成してグリッドに追加
// セルの枠線などを表示し、イベントをハンドリングする用
var rec = new Rectangle();
DateInfo dt = new DateInfo(monthInfo.Year, monthInfo.Month, String.Format("{0:00}", day));
rec.DataContext = dt;
// 枠線を調整
rec.Style = (x == 6) ? FindResource("rec-date-sat") as Style : FindResource("rec-date") as Style;
// イベント設定
rec.MouseLeftButtonDown += date_MouseLeftButtonDown;
calendarGrid.Children.Add(rec);
rec.SetValue(Grid.ColumnProperty, x);
rec.SetValue(Grid.RowProperty, y + 1);
}
return calendarGroup;
}
/// <summary>
/// グリッドのマトリックスのひな形を設定
/// </summary>
/// <param name="grid"></param>
/// <param name="rowCount"></param>
/// <param name="columnCount"></param>
private void setGridMatrix(Grid grid, int rowCount, int columnCount)
{
// 行のセット
for (int i = 0; i < rowCount; i++)
{
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
}
// 列のセット
for (int i = 0; i < columnCount; i++)
{
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
}
}
/// <summary>
/// セル(日)をクリックした際のイベントハンドラ.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void date_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// 既に選択されたセルがある場合はスタイルを戻す
if (selectedRec != null)
{
selectedRec.Style = selectedRecStyle;
}
// 選択されたセルの取得
Rectangle rec = sender as Rectangle;
// 選択セルの保持
selectedRec = rec;
selectedRecStyle = rec.Style;
// 選択時のスタイルに変更
rec.Style = FindResource("rec-date-selected") as Style;
// ラベルに日付をセット
lbSelectedDate.Content = (rec.DataContext as DateInfo).getYearMonthDayWithKanji();
}
}
}
</code></pre>
<p> </p>
<h2 id="起動してみる"><a href="#%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">起動してみる</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfCalendar3_000.jpg" alt="起動後画面" /></p>
<p>年月の時と同様、6年分のリストを作成しデフォルト表示を当年としました。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfCalendar3_001.jpg" alt="年を変更" /></p>
<p>年を変更した際の表示です。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfCalendar3_002.jpg" alt="選択した際の表示" /></p>
<p>セルを選択するとちゃんと日付が表示されます。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfCalendar3_003.jpg" alt="サイズを小さくした表示" /></p>
<p>少し分かりにくいですが、画面サイズを縮小した際の表示です。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfCalendar3_004.jpg" alt="画面サイズを大きくした表示" /></p>
<p>こちらは分かりやすいですかね。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>ひとまず目標のところまで出来たので一旦完了とします。<br />
(また何か思いついたら追加で実装するかもしれません。)</p>
<p>ではでは。</p>
doraxdora
tag:crieit.net,2005:PublicArticle/15126
2019-06-19T09:36:38+09:00
2019-06-19T09:36:38+09:00
https://crieit.net/posts/WPF-5d0983964473b
【WPF】自作カレンダー その2(動的生成)
<p>自作カレンダーその2です。<br />
今回は、Xamlではなくコードからカレンダーを生成します。</p>
<p>最終的に年間カレンダー的なものにしようと思うので、<br />
Xamlで定義すると Grid だらけになってしまうし、色々やろうと思ったらやっぱり動的に生成した方がやりやすいような気がするので。</p>
<p>前回のプログラムはこちら。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/10/15/post-2760/" target="_blank" rel="noopener noreferrer" data-blogcard="1">【WPF】自作カレンダー その1(とりあえず当月を表示)</a></p>
<h2 id="スタイル定義の変更"><a href="#%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E5%AE%9A%E7%BE%A9%E3%81%AE%E5%A4%89%E6%9B%B4">スタイル定義の変更</a></h2>
<p>まずはスタイルの外出しをします。</p>
<p>StyleDic.xaml</p>
<pre><code><br /> <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:local="clr-namespace:CalendarSample.Style">
<!-- グループ:通常-->
<Style x:Key="gp-normal" TargetType="GroupBox" >
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Background" Value="#FFFFFFFF" />
<Setter Property="Foreground" Value="#FF777777" />
<Setter Property="Height" Value="300" />
<Setter Property="Width" Value="500" />
<Setter Property="Margin" Value="10, 10, 0, 0" />
</Style>
<!-- グリッド:カレンダー用 -->
<Style x:Key="grid-calendar" TargetType="Grid" >
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="Background" Value="#FFFFFFFF" />
<Setter Property="Height" Value="258" />
<Setter Property="Width" Value="450" />
<Setter Property="Margin" Value="0, 0, 0, 0" />
</Style>
<!-- テキストブロック:日付セル(通常) -->
<Style x:Key="txb-date" TargetType="TextBlock">
<Setter Property="FontSize" Value="12" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="Padding" Value="0, 10, 10, 0" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
<!-- テキストブロック:日付セル(土曜) -->
<Style x:Key="txb-date-sat" TargetType="TextBlock" BasedOn="{StaticResource txb-date}">
<Setter Property="Foreground" Value="Blue" />
</Style>
<!-- テキストブロック:日付セル(日曜) -->
<Style x:Key="txb-date-sun" TargetType="TextBlock" BasedOn="{StaticResource txb-date}">
<Setter Property="Foreground" Value="Red" />
</Style>
<!-- 四角形:外枠用 -->
<Style x:Key="rec-border" TargetType="Rectangle">
<Setter Property="Stroke" Value="Black" />
<Setter Property="StrokeThickness" Value="1" />
<Setter Property="Grid.ColumnSpan" Value="7" />
<Setter Property="Grid.RowSpan" Value="7" />
</Style>
<!-- 四角形:下線用 -->
<Style x:Key="rec-underlining" TargetType="Rectangle">
<Setter Property="Stroke" Value="Black" />
<Setter Property="StrokeThickness" Value="1" />
<Setter Property="Height" Value="1" />
<Setter Property="VerticalAlignment" Value="Bottom" />
<Setter Property="Grid.ColumnSpan" Value="7" />
</Style>
<!-- 四角形:曜日 -->
<Style x:Key="rec-week" TargetType="Rectangle">
<Setter Property="Fill" Value="#FF8000" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Grid.Row" Value="0" />
<Setter Property="Margin" Value="1, 1, 0, 0" />
<Setter Property="Panel.ZIndex" Value="0" />
</Style>
<!-- 四角形:曜日 -->
<Style x:Key="rec-week-sat" TargetType="Rectangle" BasedOn="{StaticResource rec-week}">
<Setter Property="Margin" Value="1, 1, 1, 0" />
</Style>
<!-- 四角形:日付セル(通常) -->
<Style x:Key="rec-date" TargetType="Rectangle">
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Fill" Value="Transparent" />
<Setter Property="Margin" Value="0, -1, -1, 0" />
<!-- トリガーを使ってマウスオーバーで背景色を変更する -->
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Trigger.Setters>
<Setter Property="Margin" Value="0, 0, 0, 0" />
<Setter Property="Fill" Value="#60d0ff" />
<Setter Property="Opacity" Value="0.1"/>
</Trigger.Setters>
</Trigger>
</Style.Triggers>
</Style>
<!-- 四角形:日付セル(土曜) → 最後の列を微調整-->
<Style x:Key="rec-date-sat" TargetType="Rectangle" BasedOn="{StaticResource rec-date}">
<Setter Property="Margin" Value="0, -1, 0, 0" />
</Style>
<!-- 四角形:日付セル(選択) -->
<Style x:Key="rec-date-selected" TargetType="Rectangle">
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Stroke" Value="Black" />
<Setter Property="StrokeDashArray" Value="1 1" />
<Setter Property="StrokeThickness" Value="1"/>
<Setter Property="Fill" Value="#007acc" />
<Setter Property="Opacity" Value="0.2"/>
</Style>
<!-- ラベル:曜日ヘッダ-->
<Style x:Key="lb-week" TargetType="Label">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="Grid.Row" Value="0" />
<Setter Property="FontSize" Value="11" />
<Setter Property="Padding" Value="0" />
</Style>
</ResourceDictionary>
</code></pre>
<p>ポイントは、日付セルの上をマウスオーバーした際と、クリックして選択した際に背景色を変更するところですかね。</p>
<h2 id="画面の変更"><a href="#%E7%94%BB%E9%9D%A2%E3%81%AE%E5%A4%89%E6%9B%B4">画面の変更</a></h2>
<p>画面に年月を選択するコンボボックスと、選択された日付を表示するラベルを追加しました。<br />
後は カレンダー用の Grid がなくなってすっきりしました。</p>
<p>MainWIndow.xaml</p>
<pre><code><br /><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="カレンダーサンプル" Height="400" Width="525">
<Window.Resources>
<ResourceDictionary Source="/Style/StyleDic.xaml"/>
</Window.Resources>
<Grid x:Name="MainContainer">
<Label x:Name="lbYearMonth" Content="年月:" HorizontalAlignment="Left" Margin="10,20,0,0" VerticalAlignment="Top" />
<ComboBox x:Name="cbYearMonth" HorizontalAlignment="Left" Margin="61,20,0,0" VerticalAlignment="Top" Width="120" SelectionChanged="cbYearMonth_SelectionChanged"/>
<Grid x:Name="CalendarContainer" HorizontalAlignment="Left" Height="317" Margin="0,53,0,0" VerticalAlignment="Top" Width="517"/>
<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>
</Mah:MetroWindow>
</code></pre>
<h2 id="プログラム修正"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E4%BF%AE%E6%AD%A3">プログラム修正</a></h2>
<h3 id="新規クラス追加"><a href="#%E6%96%B0%E8%A6%8F%E3%82%AF%E3%83%A9%E3%82%B9%E8%BF%BD%E5%8A%A0">新規クラス追加</a></h3>
<p>新規で、年月コンボボックス用と、日付セル用のクラスを追加します。</p>
<p><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z9z84zrpz78zez89zz80zz74zz70ziz73z2qz76zgqnz66z0uyz82zz89zz78zz83zhjez73zj">MonthInfo.cs<br />
</span></p>
<pre><code><br />using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CalendarSample
{
/// <summary>
/// 年月情報
/// </summary>
public class MonthInfo
{
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="yearMonth"></param>
public MonthInfo(String yearMonth)
{
this.YearMonth = yearMonth;
this.YearMonthWithKanji = getYear() + "年" + getMonth() + "月";
}
/// <summary>
/// 年月
/// </summary>
public String YearMonth { set; get; }
/// <summary>
/// 年月(YYYY年MM月)
/// </summary>
public String YearMonthWithKanji { set; get; }
/// <summary>
/// 年を返します.
/// </summary>
/// <returns></returns>
public String getYear()
{
if (String.IsNullOrEmpty(YearMonth)) return "";
return YearMonth.Substring(0, 4);
}
/// <summary>
/// 月を返します.
/// </summary>
/// <returns></returns>
public String getMonth()
{
if (String.IsNullOrEmpty(YearMonth)) return "";
return YearMonth.Substring(4, 2);
}
}
}
</code></pre>
<p>DateInfo.cs</p>
<pre><code><br />using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CalendarSample
{
/// <summary>
/// 日付情報
/// </summary>
public class DateInfo : MonthInfo
{
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="yearMonth"></param>
/// <param name="day"></param>
public DateInfo(String yearMonth, String day) : base(yearMonth)
{
this.YearMonthDay = yearMonth + day;
this.Date = new DateTime(int.Parse(getYear()), int.Parse(getMonth()), int.Parse(day));
}
public DateTime Date { set; get; }
/// <summary>
/// 年月日
/// </summary>
public String YearMonthDay { set; get; }
/// <summary>
/// 年月日(YYYY年MM月DD日)
/// </summary>
public String getYearMonthDayWithKanji()
{
return String.Format("{0:yyyy年MM月dd日(ddd)}", Date);
}
/// <summary>
/// 日を返します.
/// </summary>
/// <returns></returns>
public String getDay()
{
if (String.IsNullOrEmpty(YearMonthDay)) return "";
return YearMonthDay.Substring(6, 2);
}
}
}
</code></pre>
<h3 id="コードビハインドの修正"><a href="#%E3%82%B3%E3%83%BC%E3%83%89%E3%83%93%E3%83%8F%E3%82%A4%E3%83%B3%E3%83%89%E3%81%AE%E4%BF%AE%E6%AD%A3">コードビハインドの修正</a></h3>
<p>年月コンボボックスの項目設定と、カレンダーの生成メソッドを追加したりしました。</p>
<p>MainWindow.xaml.cs</p>
<pre><code>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using MahApps.Metro.Controls;
namespace CalendarSample
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : MetroWindow
{
private Rectangle selectedRec;
private Style selectedRecStyle;
public MainWindow()
{
InitializeComponent();
// 前月から6カ月分のリストを作成し、当月を選択させる
List<MonthInfo> list = new List<MonthInfo>();
DateTime now = DateTime.Now;
DateTime dt = now.AddMonths(-1);
for (int i = 0; i < 6; i++ )
{
list.Add(new MonthInfo(String.Format("{0:yyyyMM}", dt)));
dt = dt.AddMonths(1);
}
this.cbYearMonth.ItemsSource = list;
this.cbYearMonth.DisplayMemberPath = "YearMonthWithKanji";
this.cbYearMonth.SelectedIndex = 1;
createCalendar(this.cbYearMonth.SelectedItem as MonthInfo);
}
/// <summary>
/// 年月コンボの選択変更イベントハンドラー.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void cbYearMonth_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
createCalendar(cbYearMonth.SelectedItem as MonthInfo);
}
/// <summary>
/// 指定された年月のカレンダーを作成
/// </summary>
/// <param name="monthInfo"></param>
private void createCalendar(MonthInfo monthInfo) {
CalendarContainer.Children.Clear();
// グループボックス
GroupBox calendarGroup1 = new GroupBox();
calendarGroup1.Header = monthInfo.YearMonthWithKanji;
calendarGroup1.Style = FindResource("gp-normal") as Style;
// グリッド
Grid calendarGrid1 = new Grid();
calendarGrid1.Style = FindResource("grid-calendar") as Style;
calendarGrid1.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
calendarGrid1.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
calendarGrid1.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
calendarGrid1.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
calendarGrid1.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
calendarGrid1.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
calendarGrid1.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
calendarGrid1.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(20) });
calendarGrid1.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
calendarGrid1.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
calendarGrid1.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
calendarGrid1.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
calendarGrid1.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
// グリッド枠線
Rectangle border = new Rectangle();
border.Style = FindResource("rec-border") as Style;
calendarGrid1.Children.Add(border);
for (int col = 0; col < 7; col++)
{
Rectangle week = new Rectangle();
week.Style = (col == 6) ? FindResource("rec-week-sat") as Style : FindResource("rec-week") as Style;
week.SetValue(Grid.ColumnProperty, col);
calendarGrid1.Children.Add(week);
Label lbWeek = new Label();
lbWeek.Style = FindResource("lb-week") as Style;
lbWeek.Content = ("日月火水木金土").Substring(col, 1);
lbWeek.SetValue(Grid.ColumnProperty, col);
calendarGrid1.Children.Add(lbWeek);
}
// ヘッダ行下線
Rectangle underlining = new Rectangle();
underlining.Style = FindResource("rec-underlining") as Style;
calendarGrid1.Children.Add(underlining);
// グループボックスにグリッドを追加
calendarGroup1.Content = calendarGrid1;
CalendarContainer.Children.Add(calendarGroup1);
// 当月の月初を取得
var firstDate = new DateTime(int.Parse(monthInfo.getYear()), int.Parse(monthInfo.getMonth()), 1);
// 曜日番号の取得
int dayOfWeek = (int)firstDate.DayOfWeek;
// 月末を取得
int lastDay = firstDate.AddMonths(1).AddDays(-1).Day;
// 1日から月末までを走査
for (int day = 1; day <= lastDay; day++)
{
// セル位置
int index = (day - 1) + dayOfWeek;
// 横位置
int x = index % 7;
// 縦位置
int y = index / 7;
// テキストブロックを生成してグリッドに追加
var tb = new TextBlock();
tb.Text = string.Format("{0}", day);
// 土日は文字色を変更する
if (x == 0)
{
tb.Style = FindResource("txb-date-sun") as Style;
}
else if (x == 6)
{
tb.Style = FindResource("txb-date-sat") as Style;
}
else
{
tb.Style = FindResource("txb-date") as Style;
}
calendarGrid1.Children.Add(tb);
tb.SetValue(Grid.ColumnProperty, x);
tb.SetValue(Grid.RowProperty, y + 1);
// 四角形を生成してグリッドに追加
// セルの枠線などを表示し、イベントをハンドリングする用
var rec = new Rectangle();
DateInfo dt = new DateInfo(monthInfo.YearMonth, string.Format("{0:00}", day));
rec.DataContext = dt;
// 枠線を調整
rec.Style = (x == 6) ? FindResource("rec-date-sat") as Style : FindResource("rec-date") as Style;
// イベント設定
rec.MouseLeftButtonDown += date_MouseLeftButtonDown;
calendarGrid1.Children.Add(rec);
rec.SetValue(Grid.ColumnProperty, x);
rec.SetValue(Grid.RowProperty, y + 1);
}
}
/// <summary>
/// セル(日)をクリックした際のイベントハンドラ.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void date_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// 既に選択されたセルがある場合はスタイルを戻す
if (selectedRec != null)
{
selectedRec.Style = selectedRecStyle;
}
// 選択されたセルの取得
Rectangle rec = sender as Rectangle;
// 選択セルの保持
selectedRec = rec;
selectedRecStyle = rec.Style;
// 選択時のスタイルに変更
rec.Style = FindResource("rec-date-selected") as Style;
// ラベルに日付をセット
lbSelectedDate.Content = (rec.DataContext as DateInfo).getYearMonthDayWithKanji();
}
}
}
</code></pre>
<p> </p>
<h2 id="起動してみる"><a href="#%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">起動してみる</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfCalendar2_000.jpg" alt="起動後画面" /></p>
<p>起動後は当月を表示するようにしました。</p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfCalendar2_001.jpg" alt="日付選択時" /></p>
<p>日付を選択すると、選択箇所の背景色が変わり、選択された日付が右上に表示されます。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>なんとなく使えそうな気がしてきました。<br />
バインディングなんかがうまく利用できていませんが、それは追々ということで。</p>
<p>次回は、年間カレンダーにしようかと思います。</p>
<p>ではでは。</p>
<p> </p>
doraxdora
tag:crieit.net,2005:PublicArticle/15122
2019-06-18T10:06:23+09:00
2019-06-18T10:07:06+09:00
https://crieit.net/posts/WPF
【WPF】自作カレンダー その1(とりあえず当月を表示)
<p>WPFには、カレンダーコントロールが標準であるんですが、<br />
スケジューラ-みたいなことはできないし、あくまで選択された日付を取得するためのものになっています。</p>
<p>常に表示して、カレンダーに対してアクションするようなコントローラーも<br />
需要はあると思うので、標準で使えるようにしてくれればいいのにと思いながらちょっと自作してみます。</p>
<p>今回は新規で専用にプロジェクトを作成します。</p>
<h2 id="プロジェクト作成"><a href="#%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E4%BD%9C%E6%88%90">プロジェクト作成</a></h2>
<p>VisualStudio2017を起動し、<br />
新規プロジェクトを作成、名前を「CalendarSample」とします。</p>
<p>作成方法などは下記の記事を参考にしていただければ。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/05/02/post-453/" target="_blank" rel="noopener noreferrer" data-blogcard="1">Visual Studio 2017 Community のインストールから Hello World</a></p>
<p>また、スタイルに「MahApps.Metro」を利用するので、<br />
分からなければこちらの記事を参考にしてください。<br />
<a target="_blank" rel="nofollow noopener" href="https://www.doraxdora.com/blog/2017/07/27/post-1871/" target="_blank" rel="noopener noreferrer" data-blogcard="1">【WPF】MahApps.Metro で見た目をスタイリッシュにしてみる</a></p>
<h2 id="プログラム実装"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E5%AE%9F%E8%A3%85">プログラム実装</a></h2>
<h3 id="スタイルの設定"><a href="#%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%81%AE%E8%A8%AD%E5%AE%9A">スタイルの設定</a></h3>
<p>App.xaml</p>
<pre><code class="xml"><Application x:Class="CalendarSample.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CalendarSample"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
</code></pre>
<p>MahApps.Metroのスタイル設定を記述します。</p>
<p>StyleDic.xaml</p>
<pre><code class="xml"><ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:local="clr-namespace:WpfApp1.Style">
<!-- グループ:通常-->
<Style x:Key="gp-normal" TargetType="GroupBox" >
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Background" Value="#FFFFFFFF" />
<Setter Property="Foreground" Value="#FF777777" />
</Style>
</ResourceDictionary>
</code></pre>
<p>プロジェクト直下に「Style」ディレクトリを追加し、上記ファイルを作成します。</p>
<h3 id="画面の作成"><a href="#%E7%94%BB%E9%9D%A2%E3%81%AE%E4%BD%9C%E6%88%90">画面の作成</a></h3>
<p>MainWindow.xaml</p>
<pre><code class="xml"><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="カレンダーサンプル" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary Source="/Style/StyleDic.xaml"/>
</Window.Resources>
<Grid>
<GroupBox x:Name="CalendarGropu1" Header="" HorizontalAlignment="Left" Height="300" Margin="10,10,0,0" VerticalAlignment="Top" Width="497" Style="{StaticResource gp-normal}">
<Grid x:Name="CalendarGrid" HorizontalAlignment="Left" Height="258" Margin="10,10,0,0" VerticalAlignment="Top" Width="467">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20" />
<RowDefinition Height="1*" />
<RowDefinition Height="1*" />
<RowDefinition Height="1*" />
<RowDefinition Height="1*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Rectangle Stroke="Black" StrokeThickness="1" Grid.ColumnSpan="7" Grid.RowSpan="7"/>
<Rectangle Fill="#ff8000" HorizontalAlignment="Stretch" Grid.Row="0" Grid.Column="0" VerticalAlignment="Stretch" Margin="1 1 0 0" Panel.ZIndex="0" />
<Rectangle Fill="#ff8000" HorizontalAlignment="Stretch" Grid.Row="0" Grid.Column="1" VerticalAlignment="Stretch" Margin="1 1 0 0" Panel.ZIndex="0"/>
<Rectangle Fill="#ff8000" HorizontalAlignment="Stretch" Grid.Row="0" Grid.Column="2" VerticalAlignment="Stretch" Margin="1 1 0 0" Panel.ZIndex="0"/>
<Rectangle Fill="#ff8000" HorizontalAlignment="Stretch" Grid.Row="0" Grid.Column="3" VerticalAlignment="Stretch" Margin="1 1 0 0" Panel.ZIndex="0"/>
<Rectangle Fill="#ff8000" HorizontalAlignment="Stretch" Grid.Row="0" Grid.Column="4" VerticalAlignment="Stretch" Margin="1 1 0 0" Panel.ZIndex="0"/>
<Rectangle Fill="#ff8000" HorizontalAlignment="Stretch" Grid.Row="0" Grid.Column="5" VerticalAlignment="Stretch" Margin="1 1 0 0" Panel.ZIndex="0"/>
<Rectangle Fill="#ff8000" HorizontalAlignment="Stretch" Grid.Row="0" Grid.Column="6" VerticalAlignment="Stretch" Margin="1 1 1 0" Panel.ZIndex="0"/>
<Rectangle Height="1" Stroke="Black" StrokeThickness="1" VerticalAlignment="Bottom" Grid.ColumnSpan="7"/>
<Label Content="日" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" FontSize="11" Padding="0"/>
<Label Content="月" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" FontSize="11" Padding="0"/>
<Label Content="火" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="2" VerticalAlignment="Center" FontSize="11" Padding="0"/>
<Label Content="水" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="3" VerticalAlignment="Center" FontSize="11" Padding="0"/>
<Label Content="木" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="4" VerticalAlignment="Center" FontSize="11" Padding="0"/>
<Label Content="金" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="5" VerticalAlignment="Center" FontSize="11" Padding="0"/>
<Label Content="土" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="6" VerticalAlignment="Center" FontSize="11" Padding="0"/>
</Grid>
</GroupBox>
</Grid>
</Mah:MetroWindow>
</code></pre>
<h3 id="コードビハインドの実装"><a href="#%E3%82%B3%E3%83%BC%E3%83%89%E3%83%93%E3%83%8F%E3%82%A4%E3%83%B3%E3%83%89%E3%81%AE%E5%AE%9F%E8%A3%85">コードビハインドの実装</a></h3>
<pre><code>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using MahApps.Metro.Controls;
namespace CalendarSample
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : MetroWindow
{
private Rectangle selectedRec;
public MainWindow()
{
InitializeComponent();
CalendarGropu1.Header = String.Format("{0:yyyy年MM月}", DateTime.Now);
// 当月の月初を取得
var firstDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
// 曜日番号の取得
int dayOfWeek = (int)firstDate.DayOfWeek;
// 月末を取得
int lastDay = firstDate.AddMonths(1).AddDays(-1).Day;
// 1日から月末までを走査
for (int day = 1; day <= lastDay; day++)
{
// セル位置
int index = (day - 1) + dayOfWeek;
// 横位置
int x = index % 7;
// 縦位置
int y = index / 7;
// 土日は文字色を変更する
Color color = Colors.Black;
if (x == 0)
{
color = Colors.Red;
}
else if (x == 6)
{
color = Colors.Blue;
}
// テキストブロックを生成してグリッドに追加
var tb = new TextBlock()
{
Text = string.Format("{0}", day),
FontSize = 12,
Foreground = new SolidColorBrush(color),
Padding = new Thickness(0, 10, 10, 0),
HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Top
};
this.CalendarGrid.Children.Add(tb);
tb.SetValue(Grid.ColumnProperty, x);
tb.SetValue(Grid.RowProperty, y + 1);
// 四角形を生成してグリッドに追加
// セルの枠線などを表示し、イベントをハンドリングする用
var rec = new Rectangle();
rec.HorizontalAlignment = HorizontalAlignment.Stretch;
rec.VerticalAlignment = VerticalAlignment.Stretch;
// 背景色を設定しないとイベントを検知できないらしいので透過色を設定
rec.Fill = Brushes.Transparent;
// 枠線を調整
rec.Margin = (x == 6) ? new Thickness(0.0, -1.0, 0.0, 0.0) : new Thickness(0.0, -1.0, -1.0, 0.0);
// イベント設定
rec.MouseLeftButtonDown += date_MouseLeftButtonDown;
this.CalendarGrid.Children.Add(rec);
rec.SetValue(Grid.ColumnProperty, x);
rec.SetValue(Grid.RowProperty, y + 1);
}
}
/// <summary>
/// セル(日)をクリックした際のイベントハンドラ.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void date_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// 既に選択されたセルがある場合は初期化
if (selectedRec != null)
{
selectedRec.StrokeDashArray = null;
selectedRec.StrokeThickness = 0;
}
// 枠線に点線をセット
Rectangle rec = sender as Rectangle;
rec.Stroke = Brushes.Black;
DoubleCollection dbc = new DoubleCollection();
dbc.Add(1);
dbc.Add(1);
rec.StrokeDashArray = dbc;
rec.StrokeThickness = 1;
// 選択セルの保持
selectedRec = rec;
}
}
}
</code></pre>
<p>ポイントは、<br />
「Grid」を使い枠組みを作成してセルに日付用の「Rectangle」、「TextBlock」を配置することです。</p>
<h2 id="起動してみる"><a href="#%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">起動してみる</a></h2>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfCalendar000.jpg" alt="image" /></p>
<p><img src="https://www.doraxdora.com/wp-content/uploads/2017/10/WpfCalendar001.jpg" alt="image" /></p>
<p>日付セルをクリックすると、枠に点線が表示されるようにしました。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>今回はここまでとなります。</p>
<p>次回以降、このカレンダーを使って色々試してみたいと思います。</p>
<p>ではでは。</p>
doraxdora