WPF - kliknięcie na datę kalendarza

0

Utworzyłem (na podstawie TextBox) nową kontrolkę do wyboru daty:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" x:Class="WpfApplication1.MainWindow"
        Title="MainWindow" Height="350" Width="525"
        xmlns:converter="clr-namespace:WpfApplication1">

    <Window.Resources>
        <converter:CalendarConverter x:Key="calendarConverter" />

        <Style x:Key="TextBoxStyle1" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
            <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
            <Setter Property="BorderBrush" Value="LightGray"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="Padding" Value="1"/>
            <Setter Property="AllowDrop" Value="true"/>
            <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
            <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
            <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TextBox}">
                        <Grid>
                            <Themes:ListBoxChrome x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="true">
                                <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            </Themes:ListBoxChrome>
                            <ToggleButton x:Name="PopupButton" OverridesDefaultStyle="True" IsTabStop="False" Focusable="False" ClickMode="Release" Background="Transparent" IsChecked="False" HorizontalAlignment="Right">
                                <ToggleButton.Style>
                                    <Style TargetType="{x:Type ToggleButton}">
                                        <Setter Property="Template">
                                            <Setter.Value>
                                                <ControlTemplate TargetType="{x:Type ToggleButton}">
                                                    <Border Background="LightGray" BorderBrush="LightGray" BorderThickness="1" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Margin="0,1,0,1">
                                                        <Path x:Name="Arrow" Data="M0,0L3.5,4 7,0z" Fill="Black" HorizontalAlignment="Center" Margin="0,1,0,0" VerticalAlignment="Center"/>
                                                    </Border>
                                                </ControlTemplate>
                                            </Setter.Value>
                                        </Setter>
                                    </Style>
                                </ToggleButton.Style>
                            </ToggleButton>
                            <Popup IsOpen="{Binding Path=IsChecked, ElementName=PopupButton, Mode=TwoWay}" x:Name="CustomPopup" StaysOpen="False" 
                               AllowsTransparency="True" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}">
                                <Calendar x:Name="CalDisplay" Focusable="False" 
                                      SelectedDate="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Text, Mode=TwoWay, Converter={StaticResource calendarConverter}}"                                       
                                      DisplayDate="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Text, Mode=OneWay, Converter={StaticResource calendarConverter}}">
                                    <Calendar.Triggers>
                                        <EventTrigger RoutedEvent="Calendar.SelectedDatesChanged">
                                            <BeginStoryboard>
                                                <Storyboard>
                                                    <BooleanAnimationUsingKeyFrames Storyboard.TargetName="PopupButton" Storyboard.TargetProperty="IsChecked">
                                                        <DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="False"></DiscreteBooleanKeyFrame>
                                                    </BooleanAnimationUsingKeyFrames>
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </EventTrigger>
                                    </Calendar.Triggers>
                                </Calendar>
                            </Popup>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>


    <Grid>
        <TextBox Width="120" Height="24" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10" Style="{DynamicResource TextBoxStyle1}"/>
    </Grid>
</Window>

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

namespace WpfApplication1
{
    [ValueConversion(typeof(DateTime), typeof(string))]
    class CalendarConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string dateString = (string)value;
            DateTime resultDateTime;

            if (DateTime.TryParse(dateString, out resultDateTime))
                return resultDateTime;

            return DateTime.Now;
        }        
        
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            DateTime date = (DateTime)value;
            return date.ToShortDateString();
        }
    }
}

Kalendarz jest zamykany po wystąpieniu zdarzenia 'SelectedDatesChanged'. Jeżeli wybiorę tą samą datę wtedy zdarzenie to nie jest uruchamiane i kalendarz nie zostanie zamknięty. Chciałbym to poprawić (z tego zdarzenia pewnie trzeba będzie zrezygnować), ale najpierw muszę wiedzieć, kiedy użytkownik kliknął na jakąś datę. W jaki sposób mogę to sprawdzić?

0

Ok, wiem już kiedy użytkownik kliknął na datę (każda data w kalendarzu to obiekt CalendarDayButton), ale to nie rozwiązało mojego problemu, nie wiedzieć czemu kalendarz jest zamykany tylko za pierwszym razem.
Nowa klasa:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows;
using System.ComponentModel;
using System.Windows.Input;
using System.Windows.Controls.Primitives;
using System.Windows.Media;

namespace WpfApplication1
{
    class CustomCalendar : Calendar
    {
        public bool IsDayClicked
        {
            get { return (bool)GetValue(IsDayClickedProperty); }
            set { SetValue(IsDayClickedProperty, value); }
        }

        public static readonly DependencyProperty IsDayClickedProperty =
            DependencyProperty.Register("IsDayClicked", typeof(bool), typeof(CustomCalendar), new PropertyMetadata(false));


        public override void OnApplyTemplate()
        {
            if (!DesignerProperties.GetIsInDesignMode(this))
            {
                base.OnApplyTemplate();

                this.PreviewMouseUp += CustomCalendar_PreviewMouseUp;
                this.MouseEnter += CustomCalendar_MouseEnter;
            }
        }

        void CustomCalendar_MouseEnter(object sender, MouseEventArgs e)
        {
            this.IsDayClicked = false;
        }

        void CustomCalendar_PreviewMouseUp(object sender, MouseButtonEventArgs e)
        {
            DependencyObject dep = (DependencyObject)e.OriginalSource;

            while ((dep != null) &&
                    !(dep is CalendarDayButton))
            {
                dep = VisualTreeHelper.GetParent(dep);
            }

            if (dep is CalendarDayButton)
            {
                this.IsDayClicked = true;
            }
        }
    }
}

Pełny projekt jest w załączniku.

1 użytkowników online, w tym zalogowanych: 0, gości: 1