{"id":26371471,"url":"https://github.com/jamesnetgroup/smartdate","last_synced_at":"2025-03-17T00:39:16.014Z","repository":{"id":264949766,"uuid":"774461807","full_name":"JamesnetGroup/smartdate","owner":"JamesnetGroup","description":null,"archived":false,"fork":false,"pushed_at":"2024-11-11T03:49:24.000Z","size":291,"stargazers_count":39,"open_issues_count":1,"forks_count":9,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-09T20:34:05.518Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JamesnetGroup.png","metadata":{"files":{"readme":"README.ko.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["vickyqu115"]}},"created_at":"2024-03-19T15:36:30.000Z","updated_at":"2025-02-19T03:04:05.000Z","dependencies_parsed_at":"2024-11-27T00:15:40.175Z","dependency_job_id":null,"html_url":"https://github.com/JamesnetGroup/smartdate","commit_stats":null,"previous_names":["jamesnetgroup/smartdate"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JamesnetGroup%2Fsmartdate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JamesnetGroup%2Fsmartdate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JamesnetGroup%2Fsmartdate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JamesnetGroup%2Fsmartdate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JamesnetGroup","download_url":"https://codeload.github.com/JamesnetGroup/smartdate/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243955737,"owners_count":20374372,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-17T00:39:15.217Z","updated_at":"2025-03-17T00:39:16.000Z","avatar_url":"https://github.com/JamesnetGroup.png","language":"C#","funding_links":["https://github.com/sponsors/vickyqu115"],"categories":[],"sub_categories":[],"readme":"# SmartDate [![English](https://img.shields.io/badge/Language-English-blue.svg)](README.md) [![中文](https://img.shields.io/badge/Language-中文-red.svg)](README.zh-CN.md) [![한국어](https://img.shields.io/badge/Language-한국어-red.svg)](README.ko.md)\n\n처음부터 새롭게 구상한 WPF용 현대적이고 사용자 정의 가능한 DatePicker 컨트롤\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![.NET](https://img.shields.io/badge/.NET-8.0-blue.svg)](https://dotnet.microsoft.com/download)\n[![Stars](https://img.shields.io/github/stars/vickyqu115/smartdate.svg)](https://github.com/vickyqu115/smartdate/stargazers)\n[![Issues](https://img.shields.io/github/issues/vickyqu115/smartdate.svg)](https://github.com/vickyqu115/smartdate/issues)\n\n## 프로젝트 개요\n\nSmartDate는 전통적인 DatePicker를 새롭게 구상한 사용자 정의 WPF 컨트롤입니다. 기본 제공되는 DatePicker를 상속받는 대신 Control 클래스부터 처음부터 구축하여, 현대적이고 유연하며 쉽게 사용자 정의할 수 있는 대안을 제공합니다. 이 프로젝트는 고급 WPF 기술과 컨트롤 개발 사례를 보여줍니다.\n\n\u003cimg src=\"https://github.com/vickyqu115/smartdate/assets/52397976/b848c8ef-b8ad-4925-bae0-f8ab142bf69a\" width=\"49%\"/\u003e\n\u003cimg src=\"https://github.com/user-attachments/assets/aef43667-102d-4889-afd4-bb318da43e83\" width=\"49%\"/\u003e\n\n## 주요 기능 및 구현 사항\n#### 1. 기초부터 시작한 사용자 정의 컨트롤 개발\n- [x] 표준 DatePicker의 복잡성을 우회하여 Control 클래스 기반으로 구축\n- [x] 날짜 선택 기능의 효율적인 구현\n- [x] 현재 UI/UX 트렌드에 맞춘 현대적인 디자인\n\n#### 2. 고급 WPF 기술\n- [x] 중요 요소에 PART_ 명명 규칙 사용\n- [x] 달력 레이아웃을 위한 UniformGrid가 적용된 사용자 정의 ListBox (CalendarBox)\n- [x] 드롭다운 달력 표시를 위한 Popup 컨트롤\n\n#### 3. Primitives 및 사용자 정의 컨트롤 통합\n- [x] 달력 활성화를 위한 사용자 정의 ToggleButton (CalendarSwitch)\n- [x] 월 이동을 위한 ChevronButton\n- [x] 요일 표시를 위한 DayOfWeek 컨트롤\n\n#### 4. 정교한 날짜 처리\n- [x] 효율적인 달력 생성 알고리즘\n- [x] 원활한 월 이동 및 날짜 선택\n\n#### 5. MVVM 친화적 설계\n- [x] 쉬운 데이터 바인딩을 위한 DependencyProperties (SelectedDate, CurrentMonth)\n- [x] 사용자 상호작용을 위한 이벤트 기반 아키텍처\n\n## 기술 심층 분석\n- **사용자 정의 컨트롤 아키텍처**: DatePicker 상속의 복잡성을 피하고 Control 클래스에서 복잡한 컨트롤을 구축하는 방법을 보여줍니다.\n- **PART_ 컨트롤 상호작용**: WPF의 핵심 패턴인 코드 비하인드 상호작용을 위한 PART_ 명명 요소 사용을 보여줍니다.\n- **ListBox 사용자 정의**: UniformGrid를 사용한 수정된 ListBox로 사용자 정의 달력을 구현하여 고급 ItemsPanel 사용자 정의를 보여줍니다.\n- **Popup 관리**: 드롭다운 기능을 위한 Popup 컨트롤의 효율적인 처리를 보여줍니다.\n- **날짜 로직**: 정교한 날짜 계산 및 달력 생성 알고리즘을 구현합니다.\n\n## 기술 스택\n- WPF (Windows Presentation Foundation)\n- .NET 8.0\n- C# 10.0\n- XAML\n\n## 시작하기\n### 필요 조건\n- Visual Studio 2022 이상\n- .NET 8.0 SDK\n\n### 설치 및 실행\n#### 1. 리포지토리 복제:\n\n```\ngit clone https://github.com/vickyqu115/smartdate.git\n```\n\n#### 2. 솔루션 열기\n- [x] Visual Studio\n- [x] Visual Studio Code\n- [x] JetBrains Rider\n\n\u003cimg src=\"https://github.com/user-attachments/assets/af70f422-7057-4e77-a54d-042ee8358d2a\" width=\"32%\"/\u003e\n\u003cimg src=\"https://github.com/user-attachments/assets/e4feaa10-a107-4b58-8d13-1d8be620ec62\" width=\"32%\"/\u003e\n\u003cimg src=\"https://github.com/user-attachments/assets/5ff487f6-55e4-43e1-9abf-f8d419ee6943\" width=\"32%\"/\u003e\n\n#### 3. 빌드 및 실행\n- [x] SmartDateApp을 시작 프로젝트로 설정\n- [x] F5를 누르거나 실행 버튼 클릭\n- [x] Windows 11 권장\n\n## 학습 자료\n- [구현에 대한 상세 아티클 (jamesnet.dev)](https://jamesnet.dev/article/43)\n- [YouTube 튜토리얼 (영어)](https://bit.ly/4c8uGr3)\n- [BiliBili 튜토리얼 (중국어)](https://bit.ly/3xOeyMJ)\n- [CodeProject 아티클](https://bit.ly/4du4hVD)\n\n## 기여하기\nSmartDate에 대한 기여를 환영합니다! 이슈를 제출하거나, 풀 리퀘스트를 생성하거나, 개선 사항을 제안해 주세요.\n\n## 라이선스\n이 프로젝트는 MIT 라이선스 하에 배포됩니다. 자세한 내용은 [LICENSE](LICENSE) 파일을 참조하세요.\n\n## 연락처\n- 웹사이트: https://jamesnet.dev\n- 이메일: vickyqu115@hotmail.com, james@jamesnet.dev\n\nSmartDate로 고급 WPF 컨트롤 개발 기술을 탐험해보세요!\n\n----\n\n## Recognizing the Issues with the WPF DatePicker\nThe WPF DatePicker is one of the core controls in WPF, with a history spanning nearly 20 years. Compared to simpler controls like Buttons, TextBoxes, or CheckBoxes, the DatePicker has a more complex structure and stages, composed of multiple controls. This complexity necessitates high expertise for customization, making it difficult to use or modify the provided outdated controls.\n\n## Understanding the WPF DatePicker\nAnalyzing and understanding the structure of the DatePicker and the interaction of its internal elements within the Template is extremely beneficial for enhancing fundamental design and analysis skills in WPF. This applies to all WPF controls, not just the DatePicker. However, since the DatePicker was designed according to outdated trends, it might be more efficient to implement a new CustomControl based on the basic Control.\n\n## Source Code Download and Setup\nThis article identifies issues with using the basic DatePicker and demonstrates how to redesign it using a CustomControl approach. It is also beneficial to download the source code via GitHub to check the results firsthand and read along with this article.\n\nFirst, download the source code using the following git command:\n```\ngit clone https://github.com/vickyqu115/smartdate\n```\n\nNext, to run the solution file from the source code, you need an environment with Windows 10 or higher, Visual Studio 2022 or Rider, and .NET 8.0.\n\n_SmartDate.sln_\n\n\u003cimg src=\"https://jamesnetdev.blob.core.windows.net/articleimages/50f4296f-2792-4bdd-9af6-1cffd2f9f8f6.png\" style=\"width: 300px\"/\u003e\n\n## Project Structure\nSmartDate consists of two projects:\n- SmartDateControl\n- SmartDateApp\n\nSmartDateControl is a CustomControl Library that includes the SmartDate class along with all other subordinate CustomControl classes. SmartDateApp is a simple application project that guides users on how to use this control.\n\n## Declaring and Using SmartDate\nThe usage is straightforward. Declare the namespace with xmlns and use SmartDate just like the standard DatePicker.\n\n```xml\n\u003cWindow x:Class=\"SmartDateApp.MainWindow\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n        xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n        xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n        xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n        xmlns:smart=\"clr-namespace:SmartDateControl.UI.Units;assembly=SmartDateControl\"\n        xmlns:theme=\"https://jamesnet.dev/xaml/presentation/themeswitch\"\n        mc:Ignorable=\"d\"\n        x:Name=\"Window\"\n        Title=\"SmartDate\" Height=\"450\" Width=\"800\" Background=\"#FFFFFF\"\u003e\n    \u003cViewbox Width=\"500\"\u003e\n        \u003cUniformGrid Margin=\"20\" Columns=\"1\" VerticalAlignment=\"Top\"\u003e\n            \u003csmart:SmartDate SelectedDate=\"{Binding Created}\"/\u003e\n            \u003cDatePicker SelectedDate=\"{Binding Created}\"/\u003e\n        \u003c/UniformGrid\u003e\n    \u003c/Viewbox\u003e\n\u003c/Window\u003e\n```\n\nSelectedDate is a DependencyProperty and uses the same DateTime? type as DatePicker’s SelectedDate.\n\n_Execution Results_\n\n\u003cimg src=\"https://jamesnetdev.blob.core.windows.net/articleimages/fbfa4cd0-4b3b-426e-b894-b20473096e33.png\" style=\"width: 300px; \"/\u003e\n\n## Definition and Utilization of CustomControl\nI have previously discussed the technology behind CustomControls in detail through four articles on CodeProject. If you need to understand and master CustomControls, please refer to these articles. Particularly, the article on RiotSlider delves deeply into the architecture of WPF CustomControls, so if you haven’t read it yet, I strongly recommend doing so.\n\nReturning to the main discussion, let’s define CustomControl. Typically, a CustomControl targets classes derived from Control, but in reality, it includes all classes derived from DependencyObject, not just those inheriting Control, such as Panels, up to Visuals like Animations. However, as mentioned earlier, it only makes sense to implement CustomControls in layers that can utilize Templates, or at least DataContext. Therefore, implementing classes derived from FrameworkElement in the CustomControl style is seen as wise.\n\n## Designing a New DatePicker: SmartDate\nThis article will detail how to implement a new CustomControl called SmartDate, derived from the most basic class, Control, without using the existing DatePicker.\n\n## Choosing Control Over ContentControl\nFirst, let’s examine the differences between ContentControl and Control. ContentControl offers not just the basic Template but also properties for Content and ContentTemplate. These properties are automatically linked through the ContentPresenter, setting up the relationship between ContentPresenter, Content, and ContentTemplate automatically. Consequently, choosing a derived control based on the basic usage of DataTemplate is advisable.\n\nIs DatePicker fundamentally a control that utilizes DataTemplate? While opinions may vary, a complex control like DatePicker typically requires multiple DataTemplates and does not resemble a standard ContentControl. Indeed, DatePicker is derived from Control, and similar types of controls usually inherit from Control. For example, ComboBox might look similar to DatePicker but is an ItemsControl with an ItemsSource property.\n\nTherefore, it is appropriate to base the implementation of SmartDate on Control, especially since SmartDate does not provide its own DataTemplate.\n\n## Utilizing DataTemplate\nThough SmartDate does not provide a DataTemplate by default, there are many points within various areas of the control where extending through DataTemplate could be beneficial.\n\nFor example, you can extend the ContentPresenter of the DayOfWeek control to add specific date processing, a common requirement among clients. This allows for various extensions such as triggers or converters for special dates.\n\nBy extending the SelectedDate binding area to a ContentPresenter, you can flexibly use it for selecting dates, incorporating formats ranging from a simple TextBlock to an editable TextBox or even including time.\n\n## Negative Views on DataTemplate\nDataTemplate fundamentally maintains versatility even in complex situations and is an essential template area for customization. However, whether to apply this versatility to specific controls like date pickers should be carefully considered. Using a DataTemplate means that all related logic must be separated into interactively implementable components. While this may seem practical, it is crucial to make sound judgments.\n\n## Key Binding Properties of SmartDate (DependencyProperty)\nThis control includes a binding property named SelectedDate of type DateTime?. Since the default value might be null, it is declared as a nullable type, used for setting the date value selected through the calendar.\n\n## SmartDate Template Design\n\nThe essential components that must be included in the ControlTemplate design are as follows:\n\n- Popup\n- ListBox\n- ToggleButton\n\nThe Popup acts as a panel to contain the ListBox, which is the calendar, and the ListBox uses an internal ItemsPanel to implement the calendar with a UniformGrid. The ToggleButton is used as the calendar icon, and toggling the button changes the IsOpen property of the Popup to control the calendar window. This setup is similar in the basic DatePicker control as well, making it very beneficial to compare it with the actual open-source code of DatePicker.\n\nLet’s now examine how the SmartDate control is structured in its Template.\n\n_SmartDate: ControlTemplate_\n\n```xml\n\u003cControlTemplate TargetType=\"{x:Type units:SmartDate}\"\u003e\n    \u003cBorder Background=\"{TemplateBinding Background}\"\n            BorderBrush=\"{TemplateBinding BorderBrush}\"\n            BorderThickness=\"{TemplateBinding BorderThickness}\" CornerRadius=\"4\"\u003e\n        \u003cGrid\u003e\n            \u003cunits:CalendarSwitch x:Name=\"PART_Switch\"/\u003e\n            \u003cPopup x:Name=\"PART_Popup\" StaysOpen=\"False\" ...\u003e\n                \u003cBorder Background=\"{TemplateBinding Background}\" ...\u003e\n                    \u003cjames:JamesGrid Rows=\"Auto,Auto,Auto\" Columns=\"*\"\u003e\n                        \u003cjames:JamesGrid Rows=\"*\" Columns=\"Auto,*,Auto\"\u003e\n                            \u003cunits:ChevronButton x:Name=\"PART_Left\" Tag=\"Left\"/\u003e\n                            \u003cTextBlock Style=\"{StaticResource MonthStyle}\"/\u003e\n                            \u003cunits:ChevronButton x:Name=\"PART_Right\" Tag=\"Right\"/\u003e\n                        \u003c/james:JamesGrid\u003e\n                        \u003cUniformGrid Columns=\"7\"\u003e\n                            \u003cunits:DayOfWeek Grid.Column=\"0\" Content=\"Su\"/\u003e\n                            \u003cunits:DayOfWeek Grid.Column=\"1\" Content=\"Mo\"/\u003e\n                            \u003cunits:DayOfWeek Grid.Column=\"2\" Content=\"Tu\"/\u003e\n                            \u003cunits:DayOfWeek Grid.Column=\"3\" Content=\"We\"/\u003e\n                            \u003cunits:DayOfWeek Grid.Column=\"4\" Content=\"Th\"/\u003e\n                            \u003cunits:DayOfWeek Grid.Column=\"5\" Content=\"Fr\"/\u003e\n                            \u003cunits:DayOfWeek Grid.Column=\"6\" Content=\"Sa\"/\u003e\n                        \u003c/UniformGrid\u003e\n                        \u003cunits:CalendarBox x:Name=\"PART_ListBox\"/\u003e\n                    \u003c/james:JamesGrid\u003e\n                \u003c/Border\u003e\n            \u003c/Popup\u003e\n        \u003c/Grid\u003e\n    \u003c/Border\u003e\n\u003c/ControlTemplate\u003e\n```\n\nAs you can see in the ControlTemplate, all previously mentioned components are included. The Popup is used as a basic control, and the CalendarSwitch is a calendar switching button that inherits from ToggleButton. Lastly, the CalendarBox, which inherits from ListBox, is used as the list control for selecting dates on the calendar.\n\nMoreover, other components included are buttons to navigate to the previous and next months, a TextBlock to display the current month, and design elements to display the days of the week.\n\n## CustomControl Not Intended for Reuse but for Internal Use Only\nThe SmartDate control is not only used by itself but also employs CustomControls within its Template. Not all CustomControls are intended for universal control implementation. In cases like SmartDate, they are implemented for specific purposes, which is a common practice from the perspective of WPF architecture.\n\nSuch types of controls are often categorized under the namespace 'Primitives.' This category includes controls like ToggleButton, Thumb, and ScrollBar, which are typically used not directly but within the internals of other controls.\n\nBased on these architectural facts about WPF, it can be seen that the structure of the SmartDate control's Template does not significantly differ from the basic patterns of WPF.\n\n## Understanding PART_ Control Items and Their Roles\nThe CustomControl structure does not automatically connect code and XAML like UserControls do. Thus, all interactions between the two are exclusively managed by _PART controls.\n\nThe predefined _PART controls include:\n- PART_Switch\n- PART_ListBox\n- PART_Left\n- PART_Right\n\nThese are assigned during the override of the SmartDate class's OnApplyTemplate method, where all necessary processes such as button events and date generation are implemented. It's a good practice to name controls with the PART_ prefix when passed through OnApplyTemplate. Moreover, naming these elements in XAML in a way that allows developers to anticipate what processes occur within the class based on the PART_ name would be exemplary.\n\n## SmartDate.cs Source Code\nNext, we will examine the core implementation contained within the SmartDate.cs class file. Key areas to focus on include:\n- Declared DependencyProperty\n- Definition of PART_ elements via OnApplyTemplate\n- Date selection control logic through the SelectedDate property\n- Utilization of SelectedItem/SelectedValue in CalendarBox\n\n _SmartDate: CustomControl_\n\n```csharp\n﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing System.Windows;\nusing System.Windows.Controls;\nusing System.Windows.Controls.Primitives;\nusing System.Windows.Data;\nusing System.Windows.Documents;\nusing System.Windows.Input;\nusing System.Windows.Media;\nusing System.Windows.Media.Imaging;\nusing System.Windows.Navigation;\nusing System.Windows.Shapes;\n\nnamespace SmartDateControl.UI.Units\n{\n    public class SmartDate : Control\n    {\n        private Popup _popup;\n        private CalendarSwitch _switch;\n        private CalendarBox _listbox;\n\n        public bool KeepPopupOpen\n        {\n            get { return (bool)GetValue(KeepPopupOpenProperty); }\n            set { SetValue(KeepPopupOpenProperty, value); }\n        }\n\n        public static readonly DependencyProperty KeepPopupOpenProperty =\n            DependencyProperty.Register(\"KeepPopupOpen\", typeof(bool), typeof(SmartDate), new PropertyMetadata(true));\n\n\n\n        public DateTime CurrentMonth\n        {\n            get { return (DateTime)GetValue(CurrentMonthProperty); }\n            set { SetValue(CurrentMonthProperty, value); }\n        }\n\n        public static readonly DependencyProperty CurrentMonthProperty =\n            DependencyProperty.Register(\"CurrentMonth\", typeof(DateTime), typeof(SmartDate), new PropertyMetadata(null));\n\n\n\n        public DateTime? SelectedDate\n        {\n            get { return (DateTime?)GetValue(SelectedDateProperty); }\n            set { SetValue(SelectedDateProperty, value); }\n        }\n\n        public static readonly DependencyProperty SelectedDateProperty =\n            DependencyProperty.Register(\"SelectedDate\", typeof(DateTime?), typeof(SmartDate), new PropertyMetadata(null));\n\n\n\n        static SmartDate()\n        {\n            DefaultStyleKeyProperty.OverrideMetadata(typeof(SmartDate), new FrameworkPropertyMetadata(typeof(SmartDate)));\n        }\n        public override void OnApplyTemplate()\n        {\n            base.OnApplyTemplate();\n\n            _popup = (Popup)GetTemplateChild(\"PART_Popup\");\n            _switch = (CalendarSwitch)GetTemplateChild(\"PART_Switch\");\n            _listbox = (CalendarBox)GetTemplateChild(\"PART_ListBox\");\n            ChevronButton leftButton = (ChevronButton)GetTemplateChild(\"PART_Left\");\n            ChevronButton rightButton = (ChevronButton)GetTemplateChild(\"PART_Right\");\n\n            _popup.Closed += _popup_Closed;\n            _switch.Click += _switch_Click;\n            _listbox.MouseLeftButtonUp += _listbox_MouseLeftButtonUp;\n\n            leftButton.Click += (s, e) =\u003e MoveMonthClick(-1);\n            rightButton.Click += (s, e) =\u003e MoveMonthClick(1);\n\n        }\n\n        private void MoveMonthClick(int month)\n        {\n            GenerateCalendar(CurrentMonth.AddMonths(month));\n        }\n\n        private void _popup_Closed(object sender, EventArgs e)\n        {\n            _switch.IsChecked = IsMouseOver;\n        }\n\n        private void _switch_Click(object sender, RoutedEventArgs e)\n        {\n            if (_switch.IsChecked == true)\n            {\n                _popup.IsOpen = true;\n\n                GenerateCalendar(SelectedDate ?? DateTime.Now);\n            }\n        }\n\n        private void _listbox_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)\n        {\n            if (_listbox.SelectedItem is CalendarBoxItem selected)\n            {\n                SelectedDate = selected.Date;\n                GenerateCalendar(selected.Date);\n\n                _popup.IsOpen = KeepPopupOpen; \n            }\n        }\n        private void GenerateCalendar(DateTime current)\n        {\n            if (current.ToString(\"yyyyMM\") == CurrentMonth.ToString(\"yyyyMM\")) return;\n\n            CurrentMonth = current;\n            _listbox.Items.Clear();\n            DateTime fDayOfMonth = new(current.Year,current.Month,1);\n            DateTime lDayOfMonth = fDayOfMonth.AddMonths(1).AddDays(-1);\n\n            int fOffset = (int)fDayOfMonth.DayOfWeek;\n            int lOffset = 6 - (int)lDayOfMonth.DayOfWeek;\n\n            DateTime fDay = fDayOfMonth.AddDays(-fOffset);\n            DateTime lDay = lDayOfMonth.AddDays(lOffset);\n\n            for (DateTime day = fDay; day \u003c= lDay; day = day.AddDays(1))\n            {\n                CalendarBoxItem boxItem = new();\n                boxItem.Date = day;\n                boxItem.DateFormat = day.ToString(\"yyyyMMdd\");\n                boxItem.Content = day.Day;\n                boxItem.IsCurrentMonth = day.Month == current.Month;\n\n                _listbox.Items.Add(boxItem);\n            }\n            if (SelectedDate != null)\n            {\n                _listbox.SelectedValue = SelectedDate.Value.ToString(\"yyyyMMdd\");\n            }\n        }\n    }\n}\n```\n\nFirstly, the DependencyProperty is scrutinized, including essential properties like SelectedDate, which maintains the selected date. The KeepPopupOpen property determines whether to keep the window open after a date selection, and the CurrentMonth property, a DateTime property unseen in standard DatePicker controls, retains the current month's position to facilitate navigation through calendar months.\n\nThe GenerateCalendar method incorporates logic to recreate the calendar based on the selected date. The Offset calculation part is noteworthy here. Current dates set the calendar display, and to include preview dates from the previous and next months, a simple but crucial calculation is required.\n\n```csharp\nDateTime fDayOfMonth = new(current.Year,current.Month,1);\nDateTime lDayOfMonth = fDayOfMonth.AddMonths(1).AddDays(-1);\n\nint fOffset = (int)fDayOfMonth.DayOfWeek;\nint lOffset = 6 - (int)lDayOfMonth.DayOfWeek;\n\nDateTime fDay = fDayOfMonth.AddDays(-fOffset);\nDateTime lDay = lDayOfMonth.AddDays(lOffset);\n```\n\nIn terms of event handling, the calendar selection event utilizes MouseLeftButtonUp to align with typical button click behaviors. It’s apt because SelectionChanged events do not trigger if the selected value is chosen again, making it unsuitable in this context.\n\nThe interaction between the ToggleButton's IsChecked state, Popup's IsOpen, and Close functionalities are all implemented via events, providing a comprehensive interaction mechanism that is beneficial to learn through direct implementation.\n\n## Additional Implementations\nThis application, crafted for tutorial purposes, allows for further functional expansions such as time selection or manual value adjustments. Implementing a calendar display tailored to specific customer requirements is also feasible within this framework.\n\n## Introduction to SmartDate Implementation Tutorials and Source Code\nThe entire process of implementing the SmartDate control is available in tutorial videos on [YouTube](https://bit.ly/3xOeyMJ) and [Bilibili](https://bit.ly/3xI9DNh) and can be inspected on [GitHub](https://github.com/vickyqu115/smartdate). The videos, just over 50 minutes long, were developed over two months while balancing other professional duties, making them high-quality educational resources available for free. It's recommended to approach these tutorials with ample time and patience to ensure thorough learning.\n\nShould you have any questions regarding WPF or related studies, feel free to engage in discussion. Our community is eager to assist in your exploration.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesnetgroup%2Fsmartdate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjamesnetgroup%2Fsmartdate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesnetgroup%2Fsmartdate/lists"}