実現したいこと
カレンダーコントロールの日付のBackgroundにトグル機能のような動きをさせたいです。
カレンダーの日付をクリックすると日付のBackground色が変わり、
もう一度クリックすると元のデフォルトのBackground色に戻る、というような動きにしたいです。
日付は複数選択可能としたいです。
試したこと
下記のコードでクリックした時色を変更するとことができましたが、
もう一度クリックしても背景色が元に戻らないです。
C#
1<Trigger Property="IsSelected" Value="True"> 2 <Setter TargetName="calDate" Property="Background" Value="#EAAA21"/> 3</Trigger>
また、カレンダーコントロールにSelectedDatesChangedイベントがありますが、
選択日付を変えずに同じ日付を連続で選択した場合、SelectedDatesChangedイベントが呼ばれません。
C#
1 private void Calendar_SelectedDatesChanged(object sender, SelectionChangedEventArgs e) 2 { 3 DateTime selectedDay = (DateTime)e.AddedItems[0]; 4 Console.WriteLine(selectedDay.ToString("yyyy/MM/dd")); 5 6 7 if (calendar.SelectedDates.Contains(selectedDay)) 8 { 9 calendar.Background = SystemColors.ControlBrush; 10 } 11 else 12 { 13 calendar.SelectedDates.Add(selectedDay); 14 calendar.Background = Brushes.Yellow; 15 } 16 }
補足情報(FW/ツールのバージョンなど)
VisualStudio2019,.netFramework4.8
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
下記のような質問は推奨されていません。
- 質問になっていない投稿
- スパムや攻撃的な表現を用いた投稿
適切な質問に修正を依頼しましょう。
また依頼した内容が修正された場合は、修正依頼を取り消すようにしましょう。
回答1件
1
ベストアンサー
カレンダーコントロールの日付のBackgroundにトグル機能のような動きをさせたいです。
日付は複数選択可能としたいです。
ListBox
でいうところのSelectionMode="Multiple"
の動作ということですね。
Calendar
のSelectionMode
にはなぜかMultiple
がありません(UWPにはあるのですが...)
Calendar.SelectionMode プロパティ (System.Windows.Controls) | Microsoft Learn
MultipleRange
はListBox
のExtended
に似た動作になります(Ctrl+クリックやドラッグで複数選択)
仕方がないのでPreviewMouseLeftButtonDown
で、そういう動作になるように捏造します。
Create a Behavior for Calendar in a WPF UserControl to Select and Unselect dates with one click
キーボード操作があると選択が消えたり面倒なことになるので、使わないようにするかつぶしておいたほうがいいでしょう。
Calendar クラス (System.Windows.Controls) | Microsoft Learn
選択日付を変えずに同じ日付を連続で選択した場合、SelectedDatesChangedイベントが呼ばれません。
選択が変わってないので当然呼ばれません。
この改造後は選択・選択解除と変更があるので呼ばれるようになります。
xml
1<Window 2 x:Class="Qil3fftqm79tcvt.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 Width="800" 6 Height="450"> 7 <Grid> 8 <Calendar 9 x:Name="calendar" 10 PreviewKeyDown="Calendar_PreviewKeyDown" 11 SelectedDatesChanged="Calendar_SelectedDatesChanged" 12 SelectionMode="MultipleRange"> 13 <Calendar.CalendarDayButtonStyle> 14 <Style BasedOn="{StaticResource {x:Type CalendarDayButton}}" TargetType="CalendarDayButton"> 15 <EventSetter Event="PreviewMouseLeftButtonDown" Handler="CalendarDayButton_PreviewMouseLeftButtonDown" /> 16 <Style.Triggers> 17 <Trigger Property="IsSelected" Value="True"> 18 <Setter Property="Background" Value="#EAAA21" /> 19 </Trigger> 20 </Style.Triggers> 21 </Style> 22 </Calendar.CalendarDayButtonStyle> 23 </Calendar> 24 </Grid> 25</Window>
cs
1using System; 2using System.Diagnostics; 3using System.Windows; 4using System.Windows.Controls; 5using System.Windows.Controls.Primitives; 6using System.Windows.Input; 7 8namespace Qil3fftqm79tcvt 9{ 10 public partial class MainWindow : Window 11 { 12 public MainWindow() => InitializeComponent(); 13 14 private void CalendarDayButton_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 15 { 16 if (sender is CalendarDayButton dayButton && !dayButton.IsBlackedOut) 17 { 18 var date = (DateTime)dayButton.DataContext; 19 20 if (calendar.SelectedDates.Contains(date)) 21 calendar.SelectedDates.Remove(date); 22 else 23 calendar.SelectedDates.Add(date); 24 25 e.Handled = true; 26 } 27 } 28 29 private void Calendar_PreviewKeyDown(object sender, KeyEventArgs e) => e.Handled = true; 30 31 private void Calendar_SelectedDatesChanged(object sender, SelectionChangedEventArgs e) 32 { 33 if (0 < e.AddedItems.Count) 34 Debug.WriteLine($"add: {(DateTime)e.AddedItems[0]:yyyy/MM/dd}"); 35 36 if (0 < e.RemovedItems.Count) 37 Debug.WriteLine($"remove: {(DateTime)e.RemovedItems[0]:yyyy/MM/dd}"); 38 } 39 } 40}
ControlTemplate
が不明なのでStyle.Triggers
を使いましたが、ControlTemplate.Triggers
でもいいです。
追記 ControlTemplate
&ResourceDictionary
版
MainWindow.xaml
xml:MainWindow.xaml
1<Window 2 x:Class="Qil3fftqm79tcvt.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 Width="800" 6 Height="600"> 7 <Grid> 8 <Calendar 9 x:Name="calendar" 10 PreviewKeyDown="Calendar_PreviewKeyDown" 11 SelectedDatesChanged="Calendar_SelectedDatesChanged" 12 SelectionMode="MultipleRange"> 13 <Calendar.CalendarDayButtonStyle> 14 <Style BasedOn="{StaticResource CalendarDayButtonStyle1}" TargetType="CalendarDayButton"> 15 <EventSetter Event="PreviewMouseLeftButtonDown" Handler="CalendarDayButton_PreviewMouseLeftButtonDown" /> 16 </Style> 17 </Calendar.CalendarDayButtonStyle> 18 </Calendar> 19 </Grid> 20</Window>
cs:MainWindow.xaml.cs
1using System; 2using System.Diagnostics; 3using System.Windows; 4using System.Windows.Controls; 5using System.Windows.Controls.Primitives; 6using System.Windows.Input; 7 8namespace Qil3fftqm79tcvt 9{ 10 public partial class MainWindow : Window 11 { 12 public MainWindow() => InitializeComponent(); 13 14 private void Calendar_PreviewKeyDown(object sender, KeyEventArgs e) => e.Handled = true; 15 16 private void Calendar_SelectedDatesChanged(object sender, SelectionChangedEventArgs e) 17 { 18 if (0 < e.AddedItems.Count) 19 Debug.WriteLine($"add: {(DateTime)e.AddedItems[0]:yyyy/MM/dd}"); 20 21 if (0 < e.RemovedItems.Count) 22 Debug.WriteLine($"remove: {(DateTime)e.RemovedItems[0]:yyyy/MM/dd}"); 23 } 24 25 private void CalendarDayButton_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 26 { 27 if (sender is CalendarDayButton dayButton && !dayButton.IsBlackedOut) 28 { 29 var date = (DateTime)dayButton.DataContext; 30 31 if (calendar.SelectedDates.Contains(date)) 32 calendar.SelectedDates.Remove(date); 33 else 34 calendar.SelectedDates.Add(date); 35 36 e.Handled = true; 37 } 38 } 39 } 40}
Dictionary1.xaml
xml:Dictionary1.xaml
1<ResourceDictionary 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 4 5 <Style x:Key="CalendarDayButtonStyle1" TargetType="{x:Type CalendarDayButton}"> 6 <Setter Property="Template"> 7 <Setter.Value> 8 <ControlTemplate TargetType="{x:Type CalendarDayButton}"> 9 <Grid x:Name="calDate" Background="White"> 10 <Border BorderBrush="Turquoise" BorderThickness="1"> 11 <StackPanel MinWidth="80" MinHeight="80"> 12 <TextBlock 13 Margin="2" 14 FontSize="16" 15 Text="{Binding StringFormat={}{0:dd}}" /> 16 <ItemsControl> 17 <ItemsControl.ItemsPanel> 18 <ItemsPanelTemplate> 19 <WrapPanel Margin="2" /> 20 </ItemsPanelTemplate> 21 </ItemsControl.ItemsPanel> 22 </ItemsControl> 23 </StackPanel> 24 </Border> 25 <Path 26 x:Name="Blackout" 27 Margin="3" 28 HorizontalAlignment="Stretch" 29 VerticalAlignment="Stretch" 30 Data="M8.1772461,11.029181 L10.433105,11.029181 L11.700684,12.801641 L12.973633,11.029181 L15.191895,11.029181 L12.844727,13.999395 L15.21875,17.060919 L12.962891,17.060919 L11.673828,15.256231 L10.352539,17.060919 L8.1396484,17.060919 L10.519043,14.042364 z" 31 Fill="#FF000000" 32 Opacity="0" 33 RenderTransformOrigin="0.5,0.5" 34 Stretch="Fill" /> 35 </Grid> 36 <ControlTemplate.Triggers> 37 <Trigger Property="IsSelected" Value="True"> 38 <Setter TargetName="calDate" Property="Background" Value="#EAAA21" /> 39 </Trigger> 40 <Trigger Property="IsBlackedOut" Value="True"> 41 <Setter TargetName="Blackout" Property="Opacity" Value="0.2" /> 42 </Trigger> 43 </ControlTemplate.Triggers> 44 </ControlTemplate> 45 </Setter.Value> 46 </Setter> 47 </Style> 48 49</ResourceDictionary>
投稿2023/04/19 21:47
編集2023/04/23 00:23総合スコア8859
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
下記のような回答は推奨されていません。
このような回答には修正を依頼しましょう。
また依頼した内容が修正された場合は、修正依頼を取り消すようにしましょう。
2023/04/21 12:08 編集
2023/04/22 14:11 編集
2023/04/22 22:06
2023/04/22 22:11
2023/04/22 23:30 編集
2023/04/22 23:58
2023/04/23 00:18
2023/04/23 00:23
2023/04/23 01:44
2023/04/23 02:15 編集
2023/04/24 05:45
2023/04/24 09:50 編集
2023/04/25 00:07 編集