Repository: dotnetprojects/WpfToolkit
Branch: master
Commit: dbe5005dd7b0
Files: 404
Total size: 9.8 MB
Directory structure:
gitextract_go_s1dlq/
├── .editorconfig
├── .github/
│ └── FUNDING.yml
├── .gitignore
├── DotNetProjects.snk
├── README.md
├── WpfToolkit/
│ ├── AssemblyAttrs.cs
│ ├── AssemblyInfo.cs
│ ├── Calendar/
│ │ ├── Microsoft/
│ │ │ └── Windows/
│ │ │ ├── Automation/
│ │ │ │ └── Peers/
│ │ │ │ ├── CalendarAutomationPeer.cs
│ │ │ │ ├── CalendarButtonAutomationPeer.cs
│ │ │ │ └── CalendarDayButtonAutomationPeer.cs
│ │ │ └── Controls/
│ │ │ ├── Calendar.cs
│ │ │ ├── CalendarBlackoutDatesCollection.cs
│ │ │ ├── CalendarButton.cs
│ │ │ ├── CalendarDateChangedEventArgs.cs
│ │ │ ├── CalendarDateRange.cs
│ │ │ ├── CalendarDateRangeChangingEventArgs.cs
│ │ │ ├── CalendarDayButton.cs
│ │ │ ├── CalendarItem.cs
│ │ │ ├── CalendarMode.cs
│ │ │ ├── CalendarModeChangedEventArgs.cs
│ │ │ ├── CalendarSelectionChangedEventArgs.cs
│ │ │ ├── CalendarSelectionMode.cs
│ │ │ ├── DateTimeHelper.cs
│ │ │ ├── KeyboardHelper.cs
│ │ │ ├── SelectedDatesCollection.cs
│ │ │ └── VisualStates.cs
│ │ └── Themes/
│ │ ├── Aero.NormalColor.xaml
│ │ ├── Classic.xaml
│ │ ├── Generic.xaml
│ │ ├── Luna.HomeStead.xaml
│ │ ├── Luna.Metallic.xaml
│ │ ├── Luna.NormalColor.xaml
│ │ └── Royale.NormalColor.xaml
│ ├── Common/
│ │ └── System/
│ │ └── Windows/
│ │ └── Controls/
│ │ ├── BindingEvaluator.cs
│ │ ├── Extensions.cs
│ │ ├── IUpdateVisualState.cs
│ │ ├── InteractionHelper.cs
│ │ ├── ItemsControlHelper.cs
│ │ ├── VisualStates.cs
│ │ ├── VisualTreeExtensions.cs
│ │ └── WeakEventListener.cs
│ ├── DataVisualization/
│ │ ├── AggregatedObservableCollection.cs
│ │ ├── AssemblyInfoShared.cs
│ │ ├── Charting/
│ │ │ ├── AnimationSequence.cs
│ │ │ ├── Axis/
│ │ │ │ ├── Axis.cs
│ │ │ │ ├── AxisIntervalType.cs
│ │ │ │ ├── AxisLabel.cs
│ │ │ │ ├── AxisLocation.cs
│ │ │ │ ├── AxisOrientation.cs
│ │ │ │ ├── CategoryAxis.cs
│ │ │ │ ├── CategorySortOrder.cs
│ │ │ │ ├── DateTimeAxis.cs
│ │ │ │ ├── DateTimeAxisLabel.cs
│ │ │ │ ├── DateTimeIntervalType.cs
│ │ │ │ ├── DisplayAxis.cs
│ │ │ │ ├── DisplayAxisGridLines.cs
│ │ │ │ ├── IAnchoredToOrigin.cs
│ │ │ │ ├── IAxis.cs
│ │ │ │ ├── IAxisListener.cs
│ │ │ │ ├── ICategoryAxis.cs
│ │ │ │ ├── IDataConsumer.cs
│ │ │ │ ├── IDataProvider.cs
│ │ │ │ ├── IRangeAxis.cs
│ │ │ │ ├── IRangeConsumer.cs
│ │ │ │ ├── IRangeProvider.cs
│ │ │ │ ├── IValueMarginConsumer.cs
│ │ │ │ ├── IValueMarginProvider.cs
│ │ │ │ ├── LinearAxis.cs
│ │ │ │ ├── LogarithmicAxis.cs
│ │ │ │ ├── NullableConverter.cs
│ │ │ │ ├── NumericAxis.cs
│ │ │ │ ├── NumericAxisLabel.cs
│ │ │ │ ├── OrientedAxisGridLines.cs
│ │ │ │ ├── RangeAxis.cs
│ │ │ │ └── ValueMargin.cs
│ │ │ ├── Chart/
│ │ │ │ ├── Chart.cs
│ │ │ │ └── SeriesHostAxesCollection.cs
│ │ │ ├── DataPoint/
│ │ │ │ ├── AreaDataPoint.cs
│ │ │ │ ├── BarDataPoint.cs
│ │ │ │ ├── BubbleDataPoint.cs
│ │ │ │ ├── CandlestickDataPoint.cs
│ │ │ │ ├── ColumnDataPoint.cs
│ │ │ │ ├── DataPoint.cs
│ │ │ │ ├── DataPointState.cs
│ │ │ │ ├── LineDataPoint.cs
│ │ │ │ ├── PieDataPoint.cs
│ │ │ │ └── ScatterDataPoint.cs
│ │ │ ├── FrameworkElementExtensions.cs
│ │ │ ├── Helper/
│ │ │ │ ├── Converters.cs
│ │ │ │ ├── FormattingConverter.cs
│ │ │ │ └── TreeHelper.cs
│ │ │ ├── IRequireSeriesHost.cs
│ │ │ ├── ISeriesHost.cs
│ │ │ ├── ISeriesHostExtensions.cs
│ │ │ ├── Pie/
│ │ │ │ ├── PieChartHelper.cs
│ │ │ │ ├── PieChartLabel.cs
│ │ │ │ └── PieChartLabelArea.cs
│ │ │ ├── Primitives/
│ │ │ │ ├── DelegatingListBox.cs
│ │ │ │ ├── Edge.cs
│ │ │ │ └── EdgePanel.cs
│ │ │ ├── ResourceDictionaryDispensedEventArgs.cs
│ │ │ ├── ResourceDictionaryDispenser.cs
│ │ │ ├── ResourceDictionaryEnumerator.cs
│ │ │ ├── Series/
│ │ │ │ ├── AreaSeries.cs
│ │ │ │ ├── BarSeries.cs
│ │ │ │ ├── BubbleSeries.cs
│ │ │ │ ├── CandlestickSeries.cs
│ │ │ │ ├── ColumnBarBaseSeries.cs
│ │ │ │ ├── ColumnSeries.cs
│ │ │ │ ├── Compatible/
│ │ │ │ │ ├── AreaSeries.cs
│ │ │ │ │ ├── BarSeries.cs
│ │ │ │ │ ├── ColumnSeries.cs
│ │ │ │ │ ├── LineSeries.cs
│ │ │ │ │ ├── ScatterSeries.cs
│ │ │ │ │ └── SelectionEnabledToSelectionModeConverter.cs
│ │ │ │ ├── DataPointSeries.cs
│ │ │ │ ├── DataPointSeriesWithAxes.cs
│ │ │ │ ├── DataPointSingleSeriesWithAxes.cs
│ │ │ │ ├── DefinitionSeries.cs
│ │ │ │ ├── IRequireGlobalSeriesIndex.cs
│ │ │ │ ├── ISeries.cs
│ │ │ │ ├── LabeledPieSeries.cs
│ │ │ │ ├── LegendItem.cs
│ │ │ │ ├── LineAreaBaseSeries.cs
│ │ │ │ ├── LineSeries.cs
│ │ │ │ ├── PieSeries.cs
│ │ │ │ ├── ScatterSeries.cs
│ │ │ │ ├── Series.cs
│ │ │ │ ├── SeriesDefinition.cs
│ │ │ │ ├── SeriesSelectionMode.cs
│ │ │ │ ├── SplineSeries.cs
│ │ │ │ ├── Stacked100AreaSeries.cs
│ │ │ │ ├── Stacked100BarSeries.cs
│ │ │ │ ├── Stacked100ColumnSeries.cs
│ │ │ │ ├── Stacked100LineSeries.cs
│ │ │ │ ├── StackedAreaLineSeries.cs
│ │ │ │ ├── StackedAreaSeries.cs
│ │ │ │ ├── StackedBarColumnSeries.cs
│ │ │ │ ├── StackedBarSeries.cs
│ │ │ │ ├── StackedColumnSeries.cs
│ │ │ │ └── StackedLineSeries.cs
│ │ │ └── ValueMarginCoordinateAndOverlap.cs
│ │ ├── Collections/
│ │ │ ├── LeftLeaningRedBlackTree.cs
│ │ │ ├── MultipleDictionary.cs
│ │ │ └── OrderedMultipleDictionary.cs
│ │ ├── ColorExtensions.cs
│ │ ├── DependencyPropertyAnimationHelper.cs
│ │ ├── DesignerProperties.cs
│ │ ├── DotNetProjects.DataVisualization.Toolkit.csproj
│ │ ├── DotNetProjects.snk
│ │ ├── EnumerableExtensions.cs
│ │ ├── EnumerableFunctions.cs
│ │ ├── GenericEqualityComparer.cs
│ │ ├── GlobalSuppressions.cs
│ │ ├── GridExtensions.cs
│ │ ├── IResourceDictionaryDispenser.cs
│ │ ├── LayoutTransformControl.cs
│ │ ├── Legend/
│ │ │ └── Legend.cs
│ │ ├── NoResetObservableCollection.cs
│ │ ├── ObjectPool.cs
│ │ ├── ObservableCollectionListAdapter.cs
│ │ ├── OrientedPanel.cs
│ │ ├── Properties/
│ │ │ ├── AssemblyInfo.cs
│ │ │ ├── Resources.Designer.cs
│ │ │ └── Resources.resx
│ │ ├── Range.cs
│ │ ├── RangeEnumerableFunctions.cs
│ │ ├── ReadOnlyObservableCollection.cs
│ │ ├── ResourceDictionaryCollection.cs
│ │ ├── StoryboardQueue.cs
│ │ ├── StringFormatConverter.cs
│ │ ├── Themes/
│ │ │ └── generic.xaml
│ │ ├── Title/
│ │ │ └── Title.cs
│ │ ├── TreeMap/
│ │ │ ├── BindingExtractor.cs
│ │ │ ├── Interpolators/
│ │ │ │ ├── DoubleInterpolator.cs
│ │ │ │ ├── HSLSolidColorBrushInterpolator.cs
│ │ │ │ ├── InterpolationMode.cs
│ │ │ │ ├── Interpolator.cs
│ │ │ │ ├── RangeInterpolator.cs
│ │ │ │ └── SolidColorBrushInterpolator.cs
│ │ │ ├── Layout/
│ │ │ │ ├── SquaringAlgorithm.cs
│ │ │ │ └── TreeMapNode.cs
│ │ │ ├── TreeMap.cs
│ │ │ ├── TreeMapItemDefinition.cs
│ │ │ └── TreeMapItemDefinitionSelector.cs
│ │ ├── Tuple.cs
│ │ ├── UniqueObservableCollection.cs
│ │ ├── Unit.cs
│ │ ├── UnitValue.cs
│ │ ├── ValueHelper.cs
│ │ ├── WeakEventListener.cs
│ │ └── WeakReferenceBag.cs
│ ├── DatePicker/
│ │ ├── Microsoft/
│ │ │ └── Windows/
│ │ │ ├── Automation/
│ │ │ │ └── Peers/
│ │ │ │ └── DatePickerAutomationPeer.cs
│ │ │ └── Controls/
│ │ │ ├── DatePicker.cs
│ │ │ ├── DatePickerDateValidationErrorEventArgs.cs
│ │ │ ├── DatePickerFormat.cs
│ │ │ └── DatePickerTextBox.cs
│ │ └── Themes/
│ │ ├── Aero.NormalColor.xaml
│ │ ├── Classic.xaml
│ │ ├── Generic.xaml
│ │ ├── Luna.HomeStead.xaml
│ │ ├── Luna.Metallic.xaml
│ │ ├── Luna.NormalColor.xaml
│ │ └── Royale.NormalColor.xaml
│ ├── GlobalSuppressions.cs
│ ├── Input/
│ │ ├── AutoCompleteBox/
│ │ │ └── System/
│ │ │ └── Windows/
│ │ │ ├── Automation/
│ │ │ │ └── Peers/
│ │ │ │ └── AutoCompleteBoxAutomationPeer.cs
│ │ │ └── Controls/
│ │ │ ├── AutoCompleteBox.cs
│ │ │ ├── AutoCompleteFilter.cs
│ │ │ ├── AutoCompleteFilterMode.cs
│ │ │ ├── AutoCompleteFilterPredicate.cs
│ │ │ ├── ISelectionAdapter.cs
│ │ │ ├── ItemsControlExtensions.cs
│ │ │ ├── PopulatedEventArgs.cs
│ │ │ ├── PopulatedEventHandler.cs
│ │ │ ├── PopulatingEventArgs.cs
│ │ │ ├── PopulatingEventHandler.cs
│ │ │ ├── PopupHelper.cs
│ │ │ ├── RoutedPropertyChangingEventArgs.cs
│ │ │ ├── RoutedPropertyChangingEventHandler.cs
│ │ │ ├── SelectorSelectionAdapter.cs
│ │ │ └── ValueByStringHelper.cs
│ │ ├── DotNetProjects.Input.Toolkit.csproj
│ │ ├── DotNetProjects.Input.Toolkit.csproj.DotSettings
│ │ ├── DotNetProjects.snk
│ │ ├── GlobalSuppressions.cs
│ │ ├── Properties/
│ │ │ ├── AssemblyInfo.cs
│ │ │ ├── Resources.Designer.cs
│ │ │ └── Resources.resx
│ │ ├── Rating/
│ │ │ └── System/
│ │ │ └── Windows/
│ │ │ ├── Automation/
│ │ │ │ └── Peers/
│ │ │ │ ├── RatingAutomationPeer.cs
│ │ │ │ └── RatingItemAutomationPeer.cs
│ │ │ └── Controls/
│ │ │ ├── Clipper.cs
│ │ │ ├── EnumerableFunctions.cs
│ │ │ ├── LinearClipper.cs
│ │ │ ├── NullableConverter.cs
│ │ │ ├── Rating.cs
│ │ │ ├── RatingItem.cs
│ │ │ ├── RatingSelectionMode.cs
│ │ │ ├── Tuple.cs
│ │ │ └── TupleExtensions.cs
│ │ └── Themes/
│ │ └── Generic.xaml
│ ├── Layout/
│ │ ├── Accordion/
│ │ │ └── System/
│ │ │ └── Windows/
│ │ │ ├── Automation/
│ │ │ │ └── Peers/
│ │ │ │ ├── AccordionAutomationPeer.cs
│ │ │ │ ├── AccordionItemAutomationPeer.cs
│ │ │ │ └── AccordionItemWrapperAutomationPeer.cs
│ │ │ └── Controls/
│ │ │ ├── Accordion.cs
│ │ │ ├── AccordionAction.cs
│ │ │ ├── AccordionButton.cs
│ │ │ ├── AccordionItem.cs
│ │ │ ├── AccordionSelectionMode.cs
│ │ │ ├── ExpandableContentControl.cs
│ │ │ └── SelectionSequence.cs
│ │ ├── DotNetProjects.Layout.Toolkit.csproj
│ │ ├── DotNetProjects.snk
│ │ ├── Extensions/
│ │ │ ├── MathExtensions.cs
│ │ │ └── RectExtensions.cs
│ │ ├── GlobalSuppressions.cs
│ │ ├── Properties/
│ │ │ ├── AssemblyInfo.cs
│ │ │ ├── Resources.Designer.cs
│ │ │ └── Resources.resx
│ │ ├── System.Windows.Controls.Layout.Toolkit.XML
│ │ ├── Themes/
│ │ │ └── Generic.xaml
│ │ ├── TransitioningContentControl/
│ │ │ └── System/
│ │ │ └── Windows/
│ │ │ └── Controls/
│ │ │ └── TransitioningContentControl.cs
│ │ └── ZoomableCanvas/
│ │ ├── LinkedListExtensions.cs
│ │ ├── PriorityQuadTree.cs
│ │ ├── PriorityQueue.cs
│ │ ├── VirtualPanel.cs
│ │ └── ZoomableCanvas.cs
│ ├── Resources/
│ │ ├── ExceptionStringTable.txt
│ │ ├── SR.cs
│ │ └── SRID.cs
│ ├── Samples/
│ │ ├── Accordion/
│ │ │ ├── AccordionSample.xaml
│ │ │ ├── AccordionSample.xaml.cs
│ │ │ ├── AccordionShowcase.xaml
│ │ │ ├── AccordionShowcase.xaml.cs
│ │ │ ├── AccordionUsage.xaml
│ │ │ └── AccordionUsage.xaml.cs
│ │ ├── App.xaml
│ │ ├── App.xaml.cs
│ │ ├── AutoCompleteBox/
│ │ │ ├── AutoCompleteBoxSample.xaml
│ │ │ ├── AutoCompleteBoxSample.xaml.cs
│ │ │ ├── AutoCompleteComboBox.xaml
│ │ │ ├── AutoCompleteComboBox.xaml.cs
│ │ │ ├── AutoCompleteLambda.xaml
│ │ │ ├── AutoCompleteLambda.xaml.cs
│ │ │ ├── CustomEvents.xaml
│ │ │ ├── CustomEvents.xaml.cs
│ │ │ ├── DataGridAutoCompleteBox.xaml
│ │ │ ├── DataGridAutoCompleteBox.xaml.cs
│ │ │ ├── DataGridAutoCompleteBoxEdit.xaml
│ │ │ ├── DataGridAutoCompleteBoxEdit.xaml.cs
│ │ │ ├── DataGridSelectionAdapter.cs
│ │ │ ├── DictionaryKeyValueConverter.cs
│ │ │ ├── RandomEmployeeDetails.cs
│ │ │ ├── SampleEmployeeCollection.cs
│ │ │ ├── SearchSuggestionSample.xaml
│ │ │ └── SearchSuggestionSample.xaml.cs
│ │ ├── BlogPostData.xml
│ │ ├── Common/
│ │ │ ├── BusinessObjects/
│ │ │ │ ├── Airport.cs
│ │ │ │ ├── City.cs
│ │ │ │ ├── Contact.cs
│ │ │ │ ├── Customer.cs
│ │ │ │ ├── CustomerList.cs
│ │ │ │ ├── Department.cs
│ │ │ │ ├── Employee.cs
│ │ │ │ ├── Feature.cs
│ │ │ │ ├── MemberInfoData.cs
│ │ │ │ ├── ObjectCollection.cs
│ │ │ │ ├── Photograph.cs
│ │ │ │ └── Words.cs
│ │ │ ├── GridLengthAnimation.cs
│ │ │ ├── SharedResources.cs
│ │ │ └── WebServiceHelper.cs
│ │ ├── DataVisualisation/
│ │ │ ├── DataVisualisationSample.xaml
│ │ │ ├── DataVisualisationSample.xaml.cs
│ │ │ └── SampleDataVM.cs
│ │ ├── MainWindow.xaml
│ │ ├── MainWindow.xaml.cs
│ │ ├── Properties/
│ │ │ ├── AssemblyInfo.cs
│ │ │ ├── Resources.Designer.cs
│ │ │ ├── Resources.resx
│ │ │ ├── Settings.Designer.cs
│ │ │ └── Settings.settings
│ │ ├── Rating/
│ │ │ ├── RatingSample.xaml
│ │ │ └── RatingSample.xaml.cs
│ │ ├── Themes/
│ │ │ ├── ThemesExample.xaml
│ │ │ └── ThemesExample.xaml.cs
│ │ ├── TreeMap/
│ │ │ ├── BlogPost.cs
│ │ │ ├── TreeMapIntroduction.xaml
│ │ │ └── TreeMapIntroduction.xaml.cs
│ │ ├── WPFToolkitSamples.csproj
│ │ └── app.config
│ ├── Themes/
│ │ ├── Aero.NormalColor.xaml
│ │ ├── Classic.xaml
│ │ ├── Generic.xaml
│ │ ├── Luna.HomeStead.xaml
│ │ ├── Luna.Metallic.xaml
│ │ ├── Luna.NormalColor.xaml
│ │ └── Royale.NormalColor.xaml
│ ├── WPF.Themes/
│ │ ├── BubbleCreme/
│ │ │ └── Theme.xaml
│ │ ├── BureauBlack/
│ │ │ └── Theme.xaml
│ │ ├── BureauBlue/
│ │ │ └── Theme.xaml
│ │ ├── DavesGlossyControls/
│ │ │ └── Theme.xaml
│ │ ├── DotNetProjects.WPF.Themes.csproj
│ │ ├── DotNetProjects.snk
│ │ ├── ExpressionDark/
│ │ │ └── Theme.xaml
│ │ ├── ExpressionLight/
│ │ │ └── Theme.xaml
│ │ ├── IG/
│ │ │ ├── IG.MSControls.Toolkit.Implicit.xaml
│ │ │ ├── Styles.Shared.xaml
│ │ │ ├── Styles.WPF.xaml
│ │ │ ├── Theme.Colors.xaml
│ │ │ └── Theme.xaml
│ │ ├── JetPack/
│ │ │ ├── Assets/
│ │ │ │ ├── Brushes.xaml
│ │ │ │ ├── CoreStyles.xaml
│ │ │ │ ├── Fonts.xaml
│ │ │ │ ├── SdkStyles.xaml
│ │ │ │ └── Styles.xaml
│ │ │ ├── Helpers/
│ │ │ │ ├── DataGridCheckBoxColumnFixer.cs
│ │ │ │ └── GridLengthAnimation.cs
│ │ │ └── Theme.xaml
│ │ ├── MetroDark/
│ │ │ ├── MetroDark.MSControls.Toolkit.Implicit.xaml
│ │ │ ├── Styles.Shared.xaml
│ │ │ ├── Styles.WPF.xaml
│ │ │ ├── Theme.Colors.xaml
│ │ │ └── Theme.xaml
│ │ ├── MetroLight/
│ │ │ ├── Metro.MSControls.Toolkit.Implicit.xaml
│ │ │ ├── Styles.Shared.xaml
│ │ │ ├── Styles.WPF.xaml
│ │ │ ├── Theme.Colors.xaml
│ │ │ └── Theme.xaml
│ │ ├── MoonUICore/
│ │ │ └── Theme.xaml
│ │ ├── Office2010Blue/
│ │ │ ├── Office2010Blue.MSControls.Toolkit.Implicit.xaml
│ │ │ ├── Styles.Shared.xaml
│ │ │ ├── Styles.WPF.xaml
│ │ │ ├── Theme.Colors.xaml
│ │ │ └── Theme.xaml
│ │ ├── Properties/
│ │ │ ├── AssemblyInfo.cs
│ │ │ ├── Resources.Designer.cs
│ │ │ ├── Resources.resx
│ │ │ ├── Settings.Designer.cs
│ │ │ └── Settings.settings
│ │ ├── RainierOrange/
│ │ │ └── Theme.xaml
│ │ ├── RainierPurple/
│ │ │ └── Theme.xaml
│ │ ├── RainierRadialBlue/
│ │ │ └── Theme.xaml
│ │ ├── ShinyBlue/
│ │ │ └── Theme.xaml
│ │ ├── ShinyDarkGreen/
│ │ │ └── Theme.xaml
│ │ ├── ShinyDarkPurple/
│ │ │ └── Theme.xaml
│ │ ├── ShinyDarkTeal/
│ │ │ └── Theme.xaml
│ │ ├── ShinyRed/
│ │ │ └── Theme.xaml
│ │ ├── SunnyOrange/
│ │ │ └── Theme.xaml
│ │ ├── ThemeManager.cs
│ │ ├── TwilightBlue/
│ │ │ └── Theme.xaml
│ │ ├── UXMusingsBubblyBlue/
│ │ │ └── Theme.xaml
│ │ ├── UXMusingsGreen/
│ │ │ └── Theme.xaml
│ │ ├── UXMusingsRed/
│ │ │ └── Theme.xaml
│ │ ├── UXMusingsRoughGreen/
│ │ │ └── Theme.xaml
│ │ ├── UXMusingsRoughRed/
│ │ │ └── Theme.xaml
│ │ └── WhistlerBlue/
│ │ └── Theme.xaml
│ ├── WPFToolkit.sln
│ └── WpfTest/
│ ├── App.xaml
│ ├── App.xaml.cs
│ ├── MainWindow.xaml
│ ├── MainWindow.xaml.cs
│ └── WpfTest.csproj
├── appveyor.yml
└── build.bat
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
root = true
[*]
end_of_line = crlf
insert_final_newline = true
indent_style = space
indent_size = 4
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: jogibear9988
patreon: jogibear9988
================================================
FILE: .gitignore
================================================
# Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
[Bb]in/
[Oo]bj/
# mstest test results
TestResults
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
.vs
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.log
*.vspscc
*.vssscc
.builds
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# Installshield output folder
[Ee]xpress
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish
# Publish Web Output
*.Publish.xml
# NuGet Packages Directory
packages
*.nupkg
package/lib/
# Windows Azure Build Output
csx
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
[Bb]in
[Oo]bj
sql
TestResults
[Tt]est[Rr]esult*
*.Cache
ClientBin
[Ss]tyle[Cc]op.*
~$*
*.dbmdl
Generated_Code #added for RIA/Silverlight projects
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
================================================
FILE: README.md
================================================
DotNetProjects.Wpf.Toolkit
==========================
News
----
!!NetCore 3 support!!
Nuget
-----
A Fork of the MS Wpf Toolkit, supporting NetCore3, splited in 4 Nugets:
https://www.nuget.org/packages/DotNetProjects.WpfToolkit.Input/
https://www.nuget.org/packages/DotNetProjects.WpfToolkit.Layout/
https://www.nuget.org/packages/DotNetProjects.WpfToolkit.DataVisualization/
https://www.nuget.org/packages/DotNetProjects.WpfToolkit.Themes/
Be careful! The old nuget:
https://www.nuget.org/packages/DotNetProjects.Wpf.Toolkit/
is deprecated
And these 4 ones:
https://www.nuget.org/packages/DotNetProjects.Input.Toolkit/
https://www.nuget.org/packages/DotNetProjects.Layout.Toolkit/
https://www.nuget.org/packages/DotNetProjects.DataVisualization.Toolkit/
https://www.nuget.org/packages/DotNetProjects.WPF.Themes/
are renamed.
Info
----
wpf toolkit fork of the MS WPF Toolkit (https://wpf.codeplex.com/releases/view/40535)
Additional Features:
- Port to .NET 4.0
- Remove of Controls which exist already in .NET 4.0!
- Create Example for the Charting Controls
- Include of the WPF Theming Project
- splited into 4 nugets
- Work on Bugfixes (if someone knows some)
================================================
FILE: WpfToolkit/AssemblyAttrs.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// This file specifies various assembly level attributes.
//
//---------------------------------------------------------------------------
using System;
using System.Resources;
using System.Security;
using System.Windows;
using System.Windows.Markup;
// Needed to turn on checking of security critical call chains
[assembly:SecurityCritical]
// Needed to enable xbap scenarios
[assembly:AllowPartiallyTrustedCallers]
[assembly:CLSCompliant(true)]
[assembly:NeutralResourcesLanguage("en-US")]
[assembly:ThemeInfo(
// Specifies the location of theme specific resources
ResourceDictionaryLocation.SourceAssembly,
// Specifies the location of non-theme specific resources:
ResourceDictionaryLocation.SourceAssembly)]
[assembly:XmlnsDefinition("http://schemas.microsoft.com/wpf/2008/toolkit", "Microsoft.Windows.Controls")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/wpf/2008/toolkit", "Microsoft.Windows.Controls.Primitives")]
// This line adds the public classes in this assembly and the System.Windows namespace to
// the default WPF namespace. This makes it XAML compatible with Silverlight where VisualStateManager
// is part of the default namespace.
[assembly:XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows")]
================================================
FILE: WpfToolkit/AssemblyInfo.cs
================================================
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("WPF Toolkit")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft Corp.")]
[assembly: AssemblyProduct("WPF Toolkit")]
[assembly: AssemblyCopyright("Copyright © 2010 Microsoft Corp. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// In order to begin building localizable applications, set
// CultureYouAreCodingWith in your .csproj file
// inside a . For example, if you are using US english
// in your source files, set the to en-US. Then uncomment
// the NeutralResourceLanguage attribute below. Update the "en-US" in
// the line below to match the UICulture setting in the project file.
// [assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("5.0.*")]
[assembly: AssemblyFileVersion("5.0.*")]
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Automation/Peers/CalendarAutomationPeer.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Controls;
using Microsoft.Windows.Controls;
using Microsoft.Windows.Controls.Primitives;
namespace Microsoft.Windows.Automation.Peers
{
///
/// AutomationPeer for Calendar Control
///
public sealed class CalendarAutomationPeer : FrameworkElementAutomationPeer, IGridProvider, IMultipleViewProvider, ISelectionProvider, ITableProvider
{
///
/// Initializes a new instance of the CalendarAutomationPeer class.
///
/// Owning Calendar
public CalendarAutomationPeer(Calendar owner)
: base(owner)
{
}
#region Private Properties
private Calendar OwningCalendar
{
get
{
return this.Owner as Calendar;
}
}
private Grid OwningGrid
{
get
{
if (this.OwningCalendar != null && this.OwningCalendar.MonthControl != null)
{
if (this.OwningCalendar.DisplayMode == CalendarMode.Month)
{
return this.OwningCalendar.MonthControl.MonthView;
}
else
{
return this.OwningCalendar.MonthControl.YearView;
}
}
return null;
}
}
#endregion Private Properties
#region Public Methods
///
/// Gets the control pattern that is associated with the specified System.Windows.Automation.Peers.PatternInterface.
///
/// A value from the System.Windows.Automation.Peers.PatternInterface enumeration.
/// The object that supports the specified pattern, or null if unsupported.
public override object GetPattern(PatternInterface patternInterface)
{
switch (patternInterface)
{
case PatternInterface.Grid:
case PatternInterface.Table:
case PatternInterface.MultipleView:
case PatternInterface.Selection:
{
if (this.OwningGrid != null)
{
return this;
}
break;
}
default: break;
}
return base.GetPattern(patternInterface);
}
#endregion Public Methods
#region Protected Methods
///
/// Gets the control type for the element that is associated with the UI Automation peer.
///
/// The control type.
protected override AutomationControlType GetAutomationControlTypeCore()
{
return AutomationControlType.Calendar;
}
///
/// Called by GetClassName that gets a human readable name that, in addition to AutomationControlType,
/// differentiates the control represented by this AutomationPeer.
///
/// The string that contains the name.
protected override string GetClassNameCore()
{
return this.Owner.GetType().Name;
}
#endregion Protected Methods
#region InternalMethods
internal void RaiseSelectionEvents(SelectionChangedEventArgs e)
{
int numSelected = this.OwningCalendar.SelectedDates.Count;
int numAdded = e.AddedItems.Count;
if (AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementSelected) && numSelected == 1 && numAdded == 1)
{
CalendarDayButton selectedButton = this.OwningCalendar.FindDayButtonFromDay((DateTime)e.AddedItems[0]);
if (selectedButton != null)
{
AutomationPeer peer = FrameworkElementAutomationPeer.FromElement(selectedButton);
if (peer != null)
{
peer.RaiseAutomationEvent(AutomationEvents.SelectionItemPatternOnElementSelected);
}
}
}
else
{
if (AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementAddedToSelection))
{
foreach (DateTime date in e.AddedItems)
{
CalendarDayButton selectedButton = this.OwningCalendar.FindDayButtonFromDay(date);
if (selectedButton != null)
{
AutomationPeer peer = FrameworkElementAutomationPeer.FromElement(selectedButton);
if (peer != null)
{
peer.RaiseAutomationEvent(AutomationEvents.SelectionItemPatternOnElementAddedToSelection);
}
}
}
}
if (AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementRemovedFromSelection))
{
foreach (DateTime date in e.RemovedItems)
{
CalendarDayButton removedButton = this.OwningCalendar.FindDayButtonFromDay(date);
if (removedButton != null)
{
AutomationPeer peer = FrameworkElementAutomationPeer.FromElement(removedButton);
if (peer != null)
{
peer.RaiseAutomationEvent(AutomationEvents.SelectionItemPatternOnElementRemovedFromSelection);
}
}
}
}
}
}
#endregion InternalMethods
#region IGridProvider
int IGridProvider.ColumnCount
{
get
{
if (this.OwningGrid != null)
{
return this.OwningGrid.ColumnDefinitions.Count;
}
return 0;
}
}
int IGridProvider.RowCount
{
get
{
if (this.OwningGrid != null)
{
if (this.OwningCalendar.DisplayMode == CalendarMode.Month)
{
// In Month DisplayMode, since first row is DayTitles, we return the RowCount-1
return Math.Max(0, this.OwningGrid.RowDefinitions.Count - 1);
}
else
{
return this.OwningGrid.RowDefinitions.Count;
}
}
return 0;
}
}
IRawElementProviderSimple IGridProvider.GetItem(int row, int column)
{
if (this.OwningCalendar.DisplayMode == CalendarMode.Month)
{
// In Month DisplayMode, since first row is DayTitles, we increment the row number by 1
row++;
}
if (this.OwningGrid != null && row >= 0 && row < this.OwningGrid.RowDefinitions.Count && column >= 0 && column < this.OwningGrid.ColumnDefinitions.Count)
{
foreach (UIElement child in this.OwningGrid.Children)
{
int childRow = (int)child.GetValue(Grid.RowProperty);
int childColumn = (int)child.GetValue(Grid.ColumnProperty);
if (childRow == row && childColumn == column)
{
AutomationPeer peer = CreatePeerForElement(child);
if (peer != null)
{
return ProviderFromPeer(peer);
}
}
}
}
return null;
}
#endregion IGridProvider
#region IMultipleViewProvider
int IMultipleViewProvider.CurrentView
{
get
{
return (int)this.OwningCalendar.DisplayMode;
}
}
int[] IMultipleViewProvider.GetSupportedViews()
{
int[] supportedViews = new int[3];
supportedViews[0] = (int)CalendarMode.Month;
supportedViews[1] = (int)CalendarMode.Year;
supportedViews[2] = (int)CalendarMode.Decade;
return supportedViews;
}
string IMultipleViewProvider.GetViewName(int viewId)
{
switch (viewId)
{
case 0:
{
return SR.Get(SRID.CalendarAutomationPeer_MonthMode);
}
case 1:
{
return SR.Get(SRID.CalendarAutomationPeer_YearMode);
}
case 2:
{
return SR.Get(SRID.CalendarAutomationPeer_DecadeMode);
}
}
// TODO: update when Jolt 23302 is fixed
// throw new ArgumentOutOfRangeException("viewId", Resource.Calendar_OnDisplayModePropertyChanged_InvalidValue);
return String.Empty;
}
void IMultipleViewProvider.SetCurrentView(int viewId)
{
this.OwningCalendar.DisplayMode = (CalendarMode)viewId;
}
#endregion IMultipleViewProvider
#region ISelectionProvider
bool ISelectionProvider.CanSelectMultiple
{
get
{
return this.OwningCalendar.SelectionMode == CalendarSelectionMode.SingleRange || this.OwningCalendar.SelectionMode == CalendarSelectionMode.MultipleRange;
}
}
bool ISelectionProvider.IsSelectionRequired
{
get
{
return false;
}
}
IRawElementProviderSimple[] ISelectionProvider.GetSelection()
{
List providers = new List();
if (this.OwningGrid != null)
{
if (this.OwningCalendar.DisplayMode == CalendarMode.Month && this.OwningCalendar.SelectedDates != null && this.OwningCalendar.SelectedDates.Count != 0)
{
// return selected DayButtons
CalendarDayButton dayButton;
foreach (UIElement child in this.OwningGrid.Children)
{
int childRow = (int)child.GetValue(Grid.RowProperty);
if (childRow != 0)
{
dayButton = child as CalendarDayButton;
if (dayButton != null && dayButton.IsSelected)
{
AutomationPeer peer = CreatePeerForElement(dayButton);
if (peer != null)
{
providers.Add(ProviderFromPeer(peer));
}
}
}
}
}
else
{
// return the CalendarButton which has focus
CalendarButton calendarButton;
foreach (UIElement child in this.OwningGrid.Children)
{
calendarButton = child as CalendarButton;
if (calendarButton != null && calendarButton.IsFocused)
{
AutomationPeer peer = CreatePeerForElement(calendarButton);
if (peer != null)
{
providers.Add(ProviderFromPeer(peer));
}
break;
}
}
}
if (providers.Count > 0)
{
return providers.ToArray();
}
}
return null;
}
#endregion ISelectionProvider
#region ITableProvider
RowOrColumnMajor ITableProvider.RowOrColumnMajor
{
get
{
return RowOrColumnMajor.RowMajor;
}
}
IRawElementProviderSimple[] ITableProvider.GetColumnHeaders()
{
if (this.OwningCalendar.DisplayMode == CalendarMode.Month)
{
List providers = new List();
foreach (UIElement child in this.OwningGrid.Children)
{
int childRow = (int)child.GetValue(Grid.RowProperty);
if (childRow == 0)
{
AutomationPeer peer = CreatePeerForElement(child);
if (peer != null)
{
providers.Add(ProviderFromPeer(peer));
}
}
}
if (providers.Count > 0)
{
return providers.ToArray();
}
}
return null;
}
// If WeekNumber functionality is supported by Calendar in the future,
// this method should return weeknumbers
IRawElementProviderSimple[] ITableProvider.GetRowHeaders()
{
return null;
}
#endregion ITableProvider
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Automation/Peers/CalendarButtonAutomationPeer.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.Windows.Automation;
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Controls;
using System.Windows.Input;
using Microsoft.Windows.Controls;
using Microsoft.Windows.Controls.Primitives;
namespace Microsoft.Windows.Automation.Peers
{
///
/// AutomationPeer for CalendarButton
///
public sealed class CalendarButtonAutomationPeer : ButtonAutomationPeer, IGridItemProvider, ISelectionItemProvider
{
///
/// Initializes a new instance of the CalendarButtonAutomationPeer class.
///
/// Owning CalendarButton
public CalendarButtonAutomationPeer(CalendarButton owner)
: base(owner)
{
}
#region Private Properties
private Calendar OwningCalendar
{
get
{
return this.OwningCalendarButton.Owner;
}
}
private IRawElementProviderSimple OwningCalendarAutomationPeer
{
get
{
if (this.OwningCalendar != null)
{
AutomationPeer peer = CreatePeerForElement(this.OwningCalendar);
if (peer != null)
{
return ProviderFromPeer(peer);
}
}
return null;
}
}
private CalendarButton OwningCalendarButton
{
get
{
return this.Owner as CalendarButton;
}
}
private DateTime? Date
{
get
{
if (this.OwningCalendarButton != null && this.OwningCalendarButton.DataContext is DateTime)
{
return (DateTime?)this.OwningCalendarButton.DataContext;
}
else
{
return null;
}
}
}
#endregion Private Properties
#region Public Methods
///
/// Gets the control pattern that is associated with the specified System.Windows.Automation.Peers.PatternInterface.
///
/// A value from the System.Windows.Automation.Peers.PatternInterface enumeration.
/// The object that supports the specified pattern, or null if unsupported.
public override object GetPattern(PatternInterface patternInterface)
{
object result = null;
switch (patternInterface)
{
case PatternInterface.SelectionItem:
case PatternInterface.GridItem:
{
if (this.OwningCalendar != null && this.OwningCalendar.MonthControl != null && this.OwningCalendarButton != null)
{
result = this;
}
else
{
result = base.GetPattern(patternInterface);
}
break;
}
default:
{
result = base.GetPattern(patternInterface);
break;
}
}
return result;
}
#endregion Public methods
#region Protected Methods
///
/// Gets the control type for the element that is associated with the UI Automation peer.
///
/// The control type.
protected override AutomationControlType GetAutomationControlTypeCore()
{
return AutomationControlType.Button;
}
///
/// Called by GetClassName that gets a human readable name that, in addition to AutomationControlType,
/// differentiates the control represented by this AutomationPeer.
///
/// The string that contains the name.
protected override string GetClassNameCore()
{
return Owner.GetType().Name;
}
///
/// Overrides the GetLocalizedControlTypeCore method for CalendarButtonAutomationPeer
///
///
protected override string GetLocalizedControlTypeCore()
{
return SR.Get(SRID.CalendarAutomationPeer_CalendarButtonLocalizedControlType);
}
///
/// Overrides the GetHelpTextCore method for CalendarButtonAutomationPeer
///
///
protected override string GetHelpTextCore()
{
DateTime? date = this.Date;
return date.HasValue ? DateTimeHelper.ToLongDateString(date, DateTimeHelper.GetCulture(this.OwningCalendarButton)) : base.GetHelpTextCore();
}
///
/// Overrides the GetNameCore method for CalendarButtonAutomationPeer
///
///
protected override string GetNameCore()
{
DateTime? date = this.Date;
if (date.HasValue)
{
if (this.OwningCalendar.DisplayMode == CalendarMode.Decade)
{
return DateTimeHelper.ToYearString(date, DateTimeHelper.GetCulture(this.OwningCalendarButton));
}
else
{
return DateTimeHelper.ToYearMonthPatternString(date, DateTimeHelper.GetCulture(this.OwningCalendarButton));
}
}
else
{
return base.GetNameCore();
}
}
#endregion Protected Methods
#region IGridItemProvider
int IGridItemProvider.Column
{
get
{
return (int)this.OwningCalendarButton.GetValue(Grid.ColumnProperty);
}
}
int IGridItemProvider.ColumnSpan
{
get
{
return (int)this.OwningCalendarButton.GetValue(Grid.ColumnSpanProperty);
}
}
IRawElementProviderSimple IGridItemProvider.ContainingGrid
{
get
{
return this.OwningCalendarAutomationPeer;
}
}
int IGridItemProvider.Row
{
get
{
return (int)this.OwningCalendarButton.GetValue(Grid.RowSpanProperty);
}
}
int IGridItemProvider.RowSpan
{
get
{
return 1;
}
}
#endregion IGridItemProvider
#region ISelectionItemProvider
bool ISelectionItemProvider.IsSelected
{
get
{
return this.OwningCalendarButton.IsFocused;
}
}
IRawElementProviderSimple ISelectionItemProvider.SelectionContainer
{
get
{
return this.OwningCalendarAutomationPeer;
}
}
void ISelectionItemProvider.AddToSelection()
{
return;
}
void ISelectionItemProvider.RemoveFromSelection()
{
return;
}
void ISelectionItemProvider.Select()
{
if (this.OwningCalendarButton.IsEnabled)
{
this.OwningCalendarButton.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
}
else
{
throw new ElementNotEnabledException();
}
}
#endregion ISelectionItemProvider
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Automation/Peers/CalendarDayButtonAutomationPeer.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Controls;
using Microsoft.Windows.Controls;
using Microsoft.Windows.Controls.Primitives;
namespace Microsoft.Windows.Automation.Peers
{
///
/// AutomationPeer for CalendarDayButton
///
public sealed class CalendarDayButtonAutomationPeer : ButtonAutomationPeer, IGridItemProvider, ISelectionItemProvider, ITableItemProvider
{
///
/// Initializes a new instance of the CalendarDayButtonAutomationPeer class.
///
/// Owning CalendarDayButton
public CalendarDayButtonAutomationPeer(CalendarDayButton owner)
: base(owner)
{
}
#region Private Properties
private Microsoft.Windows.Controls.Calendar OwningCalendar
{
get
{
return this.OwningCalendarDayButton.Owner;
}
}
private IRawElementProviderSimple OwningCalendarAutomationPeer
{
get
{
if (this.OwningCalendar != null)
{
AutomationPeer peer = CreatePeerForElement(this.OwningCalendar);
if (peer != null)
{
return ProviderFromPeer(peer);
}
}
return null;
}
}
private CalendarDayButton OwningCalendarDayButton
{
get
{
return this.Owner as CalendarDayButton;
}
}
private DateTime? Date
{
get
{
if (this.OwningCalendarDayButton != null && this.OwningCalendarDayButton.DataContext is DateTime)
{
return (DateTime?)this.OwningCalendarDayButton.DataContext;
}
else
{
return null;
}
}
}
#endregion Private Properties
#region Public Methods
///
/// Gets the control pattern that is associated with the specified System.Windows.Automation.Peers.PatternInterface.
///
/// A value from the System.Windows.Automation.Peers.PatternInterface enumeration.
/// The object that supports the specified pattern, or null if unsupported.
public override object GetPattern(PatternInterface patternInterface)
{
object result = null;
switch (patternInterface)
{
case PatternInterface.SelectionItem:
case PatternInterface.GridItem:
case PatternInterface.TableItem:
{
if (this.OwningCalendar != null && this.OwningCalendarDayButton != null)
{
result = this;
}
else
{
result = base.GetPattern(patternInterface);
}
break;
}
default:
{
result = base.GetPattern(patternInterface);
break;
}
}
return result;
}
#endregion Public Methods
#region Protected Methods
///
/// Gets the control type for the element that is associated with the UI Automation peer.
///
/// The control type.
protected override AutomationControlType GetAutomationControlTypeCore()
{
return AutomationControlType.Button;
}
///
/// Called by GetClassName that gets a human readable name that, in addition to AutomationControlType,
/// differentiates the control represented by this AutomationPeer.
///
/// The string that contains the name.
protected override string GetClassNameCore()
{
return Owner.GetType().Name;
}
///
/// Overrides the GetHelpTextCore method for CalendarDayButtonAutomationPeer
///
///
protected override string GetHelpTextCore()
{
DateTime? date = this.Date;
if (date.HasValue)
{
string dateString = DateTimeHelper.ToLongDateString(Date, DateTimeHelper.GetCulture(this.OwningCalendarDayButton));
if (this.OwningCalendarDayButton.IsBlackedOut)
{
return string.Format(DateTimeHelper.GetCurrentDateFormat(), SR.Get(SRID.CalendarAutomationPeer_BlackoutDayHelpText), dateString);
}
else
{
return dateString;
}
}
else
{
return base.GetHelpTextCore();
}
}
///
/// Overrides the GetLocalizedControlTypeCore method for CalendarDayButtonAutomationPeer
///
///
protected override string GetLocalizedControlTypeCore()
{
return SR.Get(SRID.CalendarAutomationPeer_DayButtonLocalizedControlType);
}
///
/// Overrides the GetNameCore method for CalendarDayButtonAutomationPeer
///
///
protected override string GetNameCore()
{
DateTime? date = this.Date;
return date.HasValue ? DateTimeHelper.ToLongDateString(Date, DateTimeHelper.GetCulture(this.OwningCalendarDayButton)) : base.GetNameCore();
}
#endregion Protected Methods
#region IGridItemProvider
///
/// Grid item column.
///
int IGridItemProvider.Column
{
get
{
return (int)this.OwningCalendarDayButton.GetValue(Grid.ColumnProperty);
}
}
///
/// Grid item column span.
///
int IGridItemProvider.ColumnSpan
{
get { return (int)this.OwningCalendarDayButton.GetValue(Grid.ColumnSpanProperty); }
}
///
/// Grid item's containing grid.
///
IRawElementProviderSimple IGridItemProvider.ContainingGrid
{
get
{
return this.OwningCalendarAutomationPeer;
}
}
///
/// Grid item row.
///
int IGridItemProvider.Row
{
get
{
Debug.Assert((int)this.OwningCalendarDayButton.GetValue(Grid.RowProperty) > 0);
// we decrement the Row value by one since the first row is composed of DayTitles
return (int)this.OwningCalendarDayButton.GetValue(Grid.RowProperty) - 1;
}
}
///
/// Grid item row span.
///
int IGridItemProvider.RowSpan
{
get
{
return (int)this.OwningCalendarDayButton.GetValue(Grid.RowSpanProperty);
}
}
#endregion IGridItemProvider
#region ISelectionItemProvider
///
/// True if the owning CalendarDayButton is selected.
///
bool ISelectionItemProvider.IsSelected
{
get
{
return this.OwningCalendarDayButton.IsSelected;
}
}
///
/// Selection items selection container.
///
IRawElementProviderSimple ISelectionItemProvider.SelectionContainer
{
get
{
return this.OwningCalendarAutomationPeer;
}
}
///
/// Adds selection item to selection.
///
void ISelectionItemProvider.AddToSelection()
{
// Return if the item is already selected or a day is already selected in the SingleSelectionMode
if (((ISelectionItemProvider)this).IsSelected)
{
return;
}
if (EnsureSelection() && this.OwningCalendarDayButton.DataContext is DateTime)
{
if (this.OwningCalendar.SelectionMode == CalendarSelectionMode.SingleDate)
{
this.OwningCalendar.SelectedDate = (DateTime)this.OwningCalendarDayButton.DataContext;
}
else
{
this.OwningCalendar.SelectedDates.Add((DateTime)this.OwningCalendarDayButton.DataContext);
}
}
}
///
/// Removes selection item from selection.
///
void ISelectionItemProvider.RemoveFromSelection()
{
// Return if the item is not already selected.
if (!((ISelectionItemProvider)this).IsSelected)
{
return;
}
if (this.OwningCalendarDayButton.DataContext is DateTime)
{
this.OwningCalendar.SelectedDates.Remove((DateTime)this.OwningCalendarDayButton.DataContext);
}
}
///
/// Selects this item.
///
void ISelectionItemProvider.Select()
{
if (EnsureSelection())
{
this.OwningCalendar.SelectedDates.Clear();
if (this.OwningCalendarDayButton.DataContext is DateTime)
{
this.OwningCalendar.SelectedDates.Add((DateTime)this.OwningCalendarDayButton.DataContext);
}
}
}
#endregion ISelectionItemProvider
#region ITableItemProvider
///
/// Gets the table item's column headers.
///
/// The table item's column headers
IRawElementProviderSimple[] ITableItemProvider.GetColumnHeaderItems()
{
if (this.OwningCalendar != null && this.OwningCalendarAutomationPeer != null)
{
IRawElementProviderSimple[] headers = ((ITableProvider)CreatePeerForElement(this.OwningCalendar)).GetColumnHeaders();
if (headers != null)
{
int column = ((IGridItemProvider)this).Column;
return new IRawElementProviderSimple[] { headers[column] };
}
}
return null;
}
///
/// Get's the table item's row headers.
///
/// The table item's row headers
IRawElementProviderSimple[] ITableItemProvider.GetRowHeaderItems()
{
return null;
}
#endregion ITableItemProvider
#region Private Methods
private bool EnsureSelection()
{
if (!this.OwningCalendarDayButton.IsEnabled)
{
throw new ElementNotEnabledException();
}
// If the day is a blackout day or the SelectionMode is None, selection is not allowed
if (this.OwningCalendarDayButton.IsBlackedOut ||
this.OwningCalendar.SelectionMode == CalendarSelectionMode.None)
{
return false;
}
return true;
}
#endregion Private Methods
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Controls/Calendar.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Controls;
using System.Windows.Input;
using Microsoft.Windows.Automation.Peers;
using Microsoft.Windows.Controls.Primitives;
namespace Microsoft.Windows.Controls
{
///
/// Represents a control that enables a user to select a date by using a visual calendar display.
///
[TemplatePart(Name = Calendar.ElementRoot, Type = typeof(Panel))]
[TemplatePart(Name = Calendar.ElementMonth, Type = typeof(CalendarItem))]
public class Calendar : Control
{
#region Constants
private const string ElementRoot = "PART_Root";
private const string ElementMonth = "PART_CalendarItem";
private const int COLS = 7;
private const int ROWS = 7;
private const int YEAR_ROWS = 3;
private const int YEAR_COLS = 4;
private const int YEARS_PER_DECADE = 10;
#endregion Constants
#region Data
private DateTime? _hoverStart;
private DateTime? _hoverEnd;
private bool _isShiftPressed;
private DateTime? _currentDate;
private CalendarItem _monthControl;
private CalendarBlackoutDatesCollection _blackoutDates;
private SelectedDatesCollection _selectedDates;
#endregion Data
#region Public Events
public static readonly RoutedEvent SelectedDatesChangedEvent = EventManager.RegisterRoutedEvent("SelectedDatesChanged", RoutingStrategy.Direct, typeof(EventHandler), typeof(Calendar));
///
/// Occurs when a date is selected.
///
public event EventHandler SelectedDatesChanged
{
add { AddHandler(SelectedDatesChangedEvent, value); }
remove { RemoveHandler(SelectedDatesChangedEvent, value); }
}
///
/// Occurs when the DisplayDate property is changed.
///
public event EventHandler DisplayDateChanged;
///
/// Occurs when the DisplayMode property is changed.
///
public event EventHandler DisplayModeChanged;
///
/// Occurs when the SelectionMode property is changed.
///
public event EventHandler SelectionModeChanged;
#endregion Public Events
///
/// Static constructor
///
static Calendar()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Calendar), new FrameworkPropertyMetadata(typeof(Calendar)));
KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(Calendar), new FrameworkPropertyMetadata(KeyboardNavigationMode.Once));
KeyboardNavigation.DirectionalNavigationProperty.OverrideMetadata(typeof(Calendar), new FrameworkPropertyMetadata(KeyboardNavigationMode.Contained));
EventManager.RegisterClassHandler(typeof(Calendar), UIElement.GotFocusEvent, new RoutedEventHandler(OnGotFocus));
LanguageProperty.OverrideMetadata(typeof(Calendar), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnLanguageChanged)));
}
///
/// Initializes a new instance of the Calendar class.
///
public Calendar()
{
this._blackoutDates = new CalendarBlackoutDatesCollection(this);
this._selectedDates = new SelectedDatesCollection(this);
this.DisplayDate = DateTime.Today;
}
#region Public Properties
#region BlackoutDates
///
/// Gets or sets the dates that are not selectable.
///
public CalendarBlackoutDatesCollection BlackoutDates
{
get { return _blackoutDates; }
}
#endregion BlackoutDates
#region CalendarButtonStyle
///
/// Gets or sets the style for displaying a CalendarButton.
///
public Style CalendarButtonStyle
{
get { return (Style)GetValue(CalendarButtonStyleProperty); }
set { SetValue(CalendarButtonStyleProperty, value); }
}
///
/// Identifies the CalendarButtonStyle dependency property.
///
public static readonly DependencyProperty CalendarButtonStyleProperty =
DependencyProperty.Register(
"CalendarButtonStyle",
typeof(Style),
typeof(Calendar));
#endregion CalendarButtonStyle
#region CalendarDayButtonStyle
///
/// Gets or sets the style for displaying a day.
///
public Style CalendarDayButtonStyle
{
get { return (Style)GetValue(CalendarDayButtonStyleProperty); }
set { SetValue(CalendarDayButtonStyleProperty, value); }
}
///
/// Identifies the DayButtonStyle dependency property.
///
public static readonly DependencyProperty CalendarDayButtonStyleProperty =
DependencyProperty.Register(
"CalendarDayButtonStyle",
typeof(Style),
typeof(Calendar));
#endregion CalendarDayButtonStyle
#region CalendarItemStyle
///
/// Gets or sets the style for a Month.
///
public Style CalendarItemStyle
{
get { return (Style)GetValue(CalendarItemStyleProperty); }
set { SetValue(CalendarItemStyleProperty, value); }
}
///
/// Identifies the MonthStyle dependency property.
///
public static readonly DependencyProperty CalendarItemStyleProperty =
DependencyProperty.Register(
"CalendarItemStyle",
typeof(Style),
typeof(Calendar));
#endregion CalendarItemStyle
#region DisplayDate
///
/// Gets or sets the date to display.
///
///
public DateTime DisplayDate
{
get { return (DateTime)GetValue(DisplayDateProperty); }
set { SetValue(DisplayDateProperty, value); }
}
///
/// Identifies the DisplayDate dependency property.
///
public static readonly DependencyProperty DisplayDateProperty =
DependencyProperty.Register(
"DisplayDate",
typeof(DateTime),
typeof(Calendar),
new FrameworkPropertyMetadata(DateTime.MinValue, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDisplayDateChanged, CoerceDisplayDate));
///
/// DisplayDateProperty property changed handler.
///
/// Calendar that changed its DisplayDate.
/// DependencyPropertyChangedEventArgs.
private static void OnDisplayDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
Debug.Assert(c != null);
c.DisplayDateInternal = DateTimeHelper.DiscardDayTime((DateTime)e.NewValue);
c.UpdateCellItems();
c.OnDisplayDateChanged(new CalendarDateChangedEventArgs((DateTime)e.OldValue, (DateTime)e.NewValue));
}
private static object CoerceDisplayDate(DependencyObject d, object value)
{
Calendar c = d as Calendar;
DateTime date = (DateTime)value;
if (c.DisplayDateStart.HasValue && (date < c.DisplayDateStart.Value))
{
value = c.DisplayDateStart.Value;
}
else if (c.DisplayDateEnd.HasValue && (date > c.DisplayDateEnd.Value))
{
value = c.DisplayDateEnd.Value;
}
return value;
}
#endregion DisplayDate
#region DisplayDateEnd
///
/// Gets or sets the last date to be displayed.
///
///
public DateTime? DisplayDateEnd
{
get { return (DateTime?)GetValue(DisplayDateEndProperty); }
set { SetValue(DisplayDateEndProperty, value); }
}
///
/// Identifies the DisplayDateEnd dependency property.
///
public static readonly DependencyProperty DisplayDateEndProperty =
DependencyProperty.Register(
"DisplayDateEnd",
typeof(DateTime?),
typeof(Calendar),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDisplayDateEndChanged, CoerceDisplayDateEnd));
///
/// DisplayDateEndProperty property changed handler.
///
/// Calendar that changed its DisplayDateEnd.
/// DependencyPropertyChangedEventArgs.
private static void OnDisplayDateEndChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
Debug.Assert(c != null);
c.CoerceValue(DisplayDateProperty);
c.UpdateCellItems();
}
private static object CoerceDisplayDateEnd(DependencyObject d, object value)
{
Calendar c = d as Calendar;
DateTime? date = (DateTime?)value;
if (date.HasValue)
{
if (c.DisplayDateStart.HasValue && (date.Value < c.DisplayDateStart.Value))
{
value = c.DisplayDateStart;
}
DateTime? maxSelectedDate = c.SelectedDates.MaximumDate;
if (maxSelectedDate.HasValue && (date.Value < maxSelectedDate.Value))
{
value = maxSelectedDate;
}
}
return value;
}
#endregion DisplayDateEnd
#region DisplayDateStart
///
/// Gets or sets the first date to be displayed.
///
///
public DateTime? DisplayDateStart
{
get { return (DateTime?)GetValue(DisplayDateStartProperty); }
set { SetValue(DisplayDateStartProperty, value); }
}
///
/// Identifies the DisplayDateStart dependency property.
///
public static readonly DependencyProperty DisplayDateStartProperty =
DependencyProperty.Register(
"DisplayDateStart",
typeof(DateTime?),
typeof(Calendar),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDisplayDateStartChanged, CoerceDisplayDateStart));
///
/// DisplayDateStartProperty property changed handler.
///
/// Calendar that changed its DisplayDateStart.
/// DependencyPropertyChangedEventArgs.
private static void OnDisplayDateStartChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
Debug.Assert(c != null);
c.CoerceValue(DisplayDateEndProperty);
c.CoerceValue(DisplayDateProperty);
c.UpdateCellItems();
}
private static object CoerceDisplayDateStart(DependencyObject d, object value)
{
Calendar c = d as Calendar;
DateTime? date = (DateTime?)value;
if (date.HasValue)
{
DateTime? minSelectedDate = c.SelectedDates.MinimumDate;
if (minSelectedDate.HasValue && (date.Value > minSelectedDate.Value))
{
value = minSelectedDate;
}
}
return value;
}
#endregion DisplayDateStart
#region DisplayMode
///
/// Gets or sets a value indicating whether the calendar is displayed in months or years.
///
public CalendarMode DisplayMode
{
get { return (CalendarMode)GetValue(DisplayModeProperty); }
set { SetValue(DisplayModeProperty, value); }
}
///
/// Identifies the DisplayMode dependency property.
///
public static readonly DependencyProperty DisplayModeProperty =
DependencyProperty.Register(
"DisplayMode",
typeof(CalendarMode),
typeof(Calendar),
new FrameworkPropertyMetadata(CalendarMode.Month, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDisplayModePropertyChanged),
new ValidateValueCallback(IsValidDisplayMode));
///
/// DisplayModeProperty property changed handler.
///
/// Calendar that changed its DisplayMode.
/// DependencyPropertyChangedEventArgs.
private static void OnDisplayModePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
Debug.Assert(c != null);
CalendarMode mode = (CalendarMode)e.NewValue;
CalendarMode oldMode = (CalendarMode)e.OldValue;
CalendarItem monthControl = c.MonthControl;
switch (mode)
{
case CalendarMode.Month:
{
if (oldMode == CalendarMode.Year || oldMode == CalendarMode.Decade)
{
// Cancel highlight when switching to month display mode
c.HoverStart = c.HoverEnd = null;
c.CurrentDate = c.DisplayDate;
}
c.UpdateCellItems();
break;
}
case CalendarMode.Year:
case CalendarMode.Decade:
{
if (oldMode == CalendarMode.Month)
{
c.DisplayDate = c.CurrentDate;
}
c.UpdateCellItems();
break;
}
default:
Debug.Assert(false);
break;
}
c.OnDisplayModeChanged(new CalendarModeChangedEventArgs((CalendarMode)e.OldValue, mode));
}
#endregion DisplayMode
#region FirstDayOfWeek
///
/// Gets or sets the day that is considered the beginning of the week.
///
public DayOfWeek FirstDayOfWeek
{
get { return (DayOfWeek)GetValue(FirstDayOfWeekProperty); }
set { SetValue(FirstDayOfWeekProperty, value); }
}
///
/// Identifies the FirstDayOfWeek dependency property.
///
public static readonly DependencyProperty FirstDayOfWeekProperty =
DependencyProperty.Register(
"FirstDayOfWeek",
typeof(DayOfWeek),
typeof(Calendar),
new FrameworkPropertyMetadata(DateTimeHelper.GetCurrentDateFormat().FirstDayOfWeek,
OnFirstDayOfWeekChanged),
new ValidateValueCallback(IsValidFirstDayOfWeek));
///
/// FirstDayOfWeekProperty property changed handler.
///
/// Calendar that changed its FirstDayOfWeek.
/// DependencyPropertyChangedEventArgs.
private static void OnFirstDayOfWeekChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
c.UpdateCellItems();
}
#endregion FirstDayOfWeek
#region IsTodayHighlighted
///
/// Gets or sets a value indicating whether the current date is highlighted.
///
public bool IsTodayHighlighted
{
get { return (bool)GetValue(IsTodayHighlightedProperty); }
set { SetValue(IsTodayHighlightedProperty, value); }
}
///
/// Identifies the IsTodayHighlighted dependency property.
///
public static readonly DependencyProperty IsTodayHighlightedProperty =
DependencyProperty.Register(
"IsTodayHighlighted",
typeof(bool),
typeof(Calendar),
new FrameworkPropertyMetadata(true, OnIsTodayHighlightedChanged));
///
/// IsTodayHighlightedProperty property changed handler.
///
/// Calendar that changed its IsTodayHighlighted.
/// DependencyPropertyChangedEventArgs.
private static void OnIsTodayHighlightedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
int i = DateTimeHelper.CompareYearMonth(c.DisplayDateInternal, DateTime.Today);
if (i > -2 && i < 2)
{
c.UpdateCellItems();
}
}
#endregion IsTodayHighlighted
#region Language
private static void OnLanguageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
if (DependencyPropertyHelper.GetValueSource(d, Calendar.FirstDayOfWeekProperty).BaseValueSource == BaseValueSource.Default)
{
c.CoerceValue(FirstDayOfWeekProperty);
c.UpdateCellItems();
}
}
#endregion
#region SelectedDate
///
/// Gets or sets the currently selected date.
///
///
public DateTime? SelectedDate
{
get { return (DateTime?)GetValue(SelectedDateProperty); }
set { SetValue(SelectedDateProperty, value); }
}
///
/// Identifies the SelectedDate dependency property.
///
public static readonly DependencyProperty SelectedDateProperty =
DependencyProperty.Register(
"SelectedDate",
typeof(DateTime?),
typeof(Calendar),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedDateChanged));
///
/// SelectedDateProperty property changed handler.
///
/// Calendar that changed its SelectedDate.
/// DependencyPropertyChangedEventArgs.
private static void OnSelectedDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
Debug.Assert(c != null);
if (c.SelectionMode != CalendarSelectionMode.None || e.NewValue == null)
{
DateTime? addedDate;
addedDate = (DateTime?)e.NewValue;
if (IsValidDateSelection(c, addedDate))
{
if (!addedDate.HasValue)
{
c.SelectedDates.ClearInternal(true /*fireChangeNotification*/);
}
else
{
if (addedDate.HasValue && !(c.SelectedDates.Count > 0 && c.SelectedDates[0] == addedDate.Value))
{
c.SelectedDates.ClearInternal();
c.SelectedDates.Add(addedDate.Value);
}
}
// We update the current date for only the Single mode.For the other modes it automatically gets updated
if (c.SelectionMode == CalendarSelectionMode.SingleDate)
{
if (addedDate.HasValue)
{
c.CurrentDate = addedDate.Value;
}
c.UpdateCellItems();
}
}
else
{
throw new ArgumentOutOfRangeException("d", SR.Get(SRID.Calendar_OnSelectedDateChanged_InvalidValue));
}
}
else
{
throw new InvalidOperationException(SR.Get(SRID.Calendar_OnSelectedDateChanged_InvalidOperation));
}
}
#endregion SelectedDate
#region SelectedDates
// TODO: Should it be of type ObservableCollection?
///
/// Gets the dates that are currently selected.
///
public SelectedDatesCollection SelectedDates
{
get { return _selectedDates; }
}
#endregion SelectedDates
#region SelectionMode
///
/// Gets or sets the selection mode for the calendar.
///
public CalendarSelectionMode SelectionMode
{
get { return (CalendarSelectionMode)GetValue(SelectionModeProperty); }
set { SetValue(SelectionModeProperty, value); }
}
///
/// Identifies the SelectionMode dependency property.
///
public static readonly DependencyProperty SelectionModeProperty =
DependencyProperty.Register(
"SelectionMode",
typeof(CalendarSelectionMode),
typeof(Calendar),
new FrameworkPropertyMetadata(CalendarSelectionMode.SingleDate, OnSelectionModeChanged),
new ValidateValueCallback(IsValidSelectionMode));
private static void OnSelectionModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
Debug.Assert(c != null);
c.HoverStart = c.HoverEnd = null;
c.SelectedDates.ClearInternal(true /*fireChangeNotification*/);
c.OnSelectionModeChanged(EventArgs.Empty);
}
#endregion SelectionMode
#endregion Public Properties
#region Internal Events
internal event MouseButtonEventHandler DayButtonMouseUp;
internal event RoutedEventHandler DayOrMonthPreviewKeyDown;
#endregion Internal Events
#region Internal Properties
///
/// This flag is used to determine whether DatePicker should change its
/// DisplayDate because of a SelectedDate change on its Calendar
///
internal bool DatePickerDisplayDateFlag
{
get;
set;
}
internal DateTime DisplayDateInternal
{
get;
private set;
}
internal DateTime DisplayDateEndInternal
{
get
{
return this.DisplayDateEnd.GetValueOrDefault(DateTime.MaxValue);
}
}
internal DateTime DisplayDateStartInternal
{
get
{
return this.DisplayDateStart.GetValueOrDefault(DateTime.MinValue);
}
}
internal DateTime CurrentDate
{
get { return _currentDate.GetValueOrDefault(this.DisplayDateInternal); }
set { _currentDate = value; }
}
internal DateTime? HoverStart
{
get
{
return this.SelectionMode == CalendarSelectionMode.None ? null : _hoverStart;
}
set
{
_hoverStart = value;
}
}
internal DateTime? HoverEnd
{
get
{
return this.SelectionMode == CalendarSelectionMode.None ? null : _hoverEnd;
}
set
{
_hoverEnd = value;
}
}
internal CalendarItem MonthControl
{
get { return _monthControl; }
}
internal DateTime DisplayMonth
{
get
{
return DateTimeHelper.DiscardDayTime(DisplayDate);
}
}
internal DateTime DisplayYear
{
get
{
return new DateTime(DisplayDate.Year, 1, 1);
}
}
#endregion Internal Properties
#region Private Properties
private bool IsRightToLeft
{
get
{
return FlowDirection == FlowDirection.RightToLeft;
}
}
#endregion Private Properties
#region Public Methods
///
/// Invoked whenever application code or an internal process,
/// such as a rebuilding layout pass, calls the ApplyTemplate method.
///
public override void OnApplyTemplate()
{
if (_monthControl != null)
{
_monthControl.Owner = null;
}
base.OnApplyTemplate();
_monthControl = GetTemplateChild(ElementMonth) as CalendarItem;
if (_monthControl != null)
{
_monthControl.Owner = this;
}
this.CurrentDate = this.DisplayDate;
UpdateCellItems();
}
///
/// Provides a text representation of the selected date.
///
/// A text representation of the selected date, or an empty string if SelectedDate is a null reference.
public override string ToString()
{
if (this.SelectedDate != null)
{
return this.SelectedDate.Value.ToString(DateTimeHelper.GetDateFormat(DateTimeHelper.GetCulture(this)));
}
else
{
return string.Empty;
}
}
#endregion Public Methods
#region Protected Methods
protected virtual void OnSelectedDatesChanged(SelectionChangedEventArgs e)
{
RaiseEvent(e);
}
protected virtual void OnDisplayDateChanged(CalendarDateChangedEventArgs e)
{
EventHandler handler = this.DisplayDateChanged;
if (handler != null)
{
handler(this, e);
}
}
protected virtual void OnDisplayModeChanged(CalendarModeChangedEventArgs e)
{
EventHandler handler = this.DisplayModeChanged;
if (handler != null)
{
handler(this, e);
}
}
protected virtual void OnSelectionModeChanged(EventArgs e)
{
EventHandler handler = this.SelectionModeChanged;
if (handler != null)
{
handler(this, e);
}
}
///
/// Creates the automation peer for this Calendar Control.
///
///
protected override AutomationPeer OnCreateAutomationPeer()
{
return new CalendarAutomationPeer(this);
}
protected override void OnKeyDown(KeyEventArgs e)
{
if (!e.Handled)
{
e.Handled = ProcessCalendarKey(e);
}
}
protected override void OnKeyUp(KeyEventArgs e)
{
if (!e.Handled)
{
if (e.Key == Key.LeftShift || e.Key == Key.RightShift)
{
ProcessShiftKeyUp();
}
}
}
#endregion Protected Methods
#region Internal Methods
internal CalendarDayButton FindDayButtonFromDay(DateTime day)
{
if (this.MonthControl != null)
{
foreach (CalendarDayButton b in this.MonthControl.GetCalendarDayButtons())
{
if (b.DataContext is DateTime)
{
if (DateTimeHelper.CompareDays((DateTime)b.DataContext, day) == 0)
{
return b;
}
}
}
}
return null;
}
internal static bool IsValidDateSelection(Calendar cal, object value)
{
return (value == null) || (!cal.BlackoutDates.Contains((DateTime)value));
}
internal void OnDayButtonMouseUp(MouseButtonEventArgs e)
{
MouseButtonEventHandler handler = this.DayButtonMouseUp;
if (null != handler)
{
handler(this, e);
}
}
internal void OnDayOrMonthPreviewKeyDown(RoutedEventArgs e)
{
RoutedEventHandler handler = this.DayOrMonthPreviewKeyDown;
if (null != handler)
{
handler(this, e);
}
}
// If the day is a trailing day, Update the DisplayDate
internal void OnDayClick(DateTime selectedDate)
{
if (this.SelectionMode == CalendarSelectionMode.None)
{
this.CurrentDate = selectedDate;
}
if (DateTimeHelper.CompareYearMonth(selectedDate, this.DisplayDateInternal) != 0)
{
MoveDisplayTo(selectedDate);
}
else
{
UpdateCellItems();
FocusDate(selectedDate);
}
}
internal void OnCalendarButtonPressed(CalendarButton b, bool switchDisplayMode)
{
if (b.DataContext is DateTime)
{
DateTime d = (DateTime)b.DataContext;
DateTime? newDate = null;
CalendarMode newMode = CalendarMode.Month;
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
Debug.Assert(false);
break;
}
case CalendarMode.Year:
{
newDate = DateTimeHelper.SetYearMonth(this.DisplayDate, d);
newMode = CalendarMode.Month;
break;
}
case CalendarMode.Decade:
{
newDate = DateTimeHelper.SetYear(this.DisplayDate, d.Year);
newMode = CalendarMode.Year;
break;
}
default:
Debug.Assert(false);
break;
}
if (newDate.HasValue)
{
this.DisplayDate = newDate.Value;
if (switchDisplayMode)
{
this.DisplayMode = newMode;
FocusDate(this.DisplayMode == CalendarMode.Month ? this.CurrentDate : this.DisplayDate);
}
}
}
}
private DateTime? GetDateOffset(DateTime date, int offset, CalendarMode displayMode)
{
DateTime? result = null;
switch (displayMode)
{
case CalendarMode.Month:
{
result = DateTimeHelper.AddMonths(date, offset);
break;
}
case CalendarMode.Year:
{
result = DateTimeHelper.AddYears(date, offset);
break;
}
case CalendarMode.Decade:
{
result = DateTimeHelper.AddYears(this.DisplayDate, offset * YEARS_PER_DECADE);
break;
}
default:
Debug.Assert(false);
break;
}
return result;
}
private void MoveDisplayTo(DateTime? date)
{
if (date.HasValue)
{
DateTime d = date.Value.Date;
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
this.DisplayDate = DateTimeHelper.DiscardDayTime(d);
this.CurrentDate = d;
UpdateCellItems();
break;
}
case CalendarMode.Year:
case CalendarMode.Decade:
{
this.DisplayDate = d;
UpdateCellItems();
break;
}
default:
Debug.Assert(false);
break;
}
FocusDate(d);
}
}
internal void OnNextClick()
{
DateTime? nextDate = GetDateOffset(this.DisplayDate, 1, this.DisplayMode);
if (nextDate.HasValue)
{
MoveDisplayTo(DateTimeHelper.DiscardDayTime(nextDate.Value));
}
}
internal void OnPreviousClick()
{
DateTime? nextDate = GetDateOffset(this.DisplayDate, -1, this.DisplayMode);
if (nextDate.HasValue)
{
MoveDisplayTo(DateTimeHelper.DiscardDayTime(nextDate.Value));
}
}
internal void OnSelectedDatesCollectionChanged(SelectionChangedEventArgs e)
{
if (IsSelectionChanged(e))
{
if (AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementSelected) ||
AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementAddedToSelection) ||
AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementRemovedFromSelection))
{
CalendarAutomationPeer peer = FrameworkElementAutomationPeer.FromElement(this) as CalendarAutomationPeer;
if (peer != null)
{
peer.RaiseSelectionEvents(e);
}
}
CoerceFromSelection();
OnSelectedDatesChanged(e);
}
}
internal void UpdateCellItems()
{
CalendarItem monthControl = this.MonthControl;
if (monthControl != null)
{
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
monthControl.UpdateMonthMode();
break;
}
case CalendarMode.Year:
{
monthControl.UpdateYearMode();
break;
}
case CalendarMode.Decade:
{
monthControl.UpdateDecadeMode();
break;
}
default:
Debug.Assert(false);
break;
}
}
}
#endregion Internal Methods
#region Private Methods
private void CoerceFromSelection()
{
CoerceValue(DisplayDateStartProperty);
CoerceValue(DisplayDateEndProperty);
CoerceValue(DisplayDateProperty);
}
// This method adds the days that were selected by Keyboard to the SelectedDays Collection
private void AddKeyboardSelection()
{
if (this.HoverStart != null)
{
this.SelectedDates.ClearInternal();
// In keyboard selection, we are sure that the collection does not include any blackout days
this.SelectedDates.AddRange(this.HoverStart.Value, this.CurrentDate);
}
}
private static bool IsSelectionChanged(SelectionChangedEventArgs e)
{
if (e.AddedItems.Count != e.RemovedItems.Count)
{
return true;
}
foreach (DateTime addedDate in e.AddedItems)
{
if (!e.RemovedItems.Contains(addedDate))
{
return true;
}
}
return false;
}
private static bool IsValidDisplayMode(object value)
{
CalendarMode mode = (CalendarMode)value;
return mode == CalendarMode.Month
|| mode == CalendarMode.Year
|| mode == CalendarMode.Decade;
}
internal static bool IsValidFirstDayOfWeek(object value)
{
DayOfWeek day = (DayOfWeek)value;
return day == DayOfWeek.Sunday
|| day == DayOfWeek.Monday
|| day == DayOfWeek.Tuesday
|| day == DayOfWeek.Wednesday
|| day == DayOfWeek.Thursday
|| day == DayOfWeek.Friday
|| day == DayOfWeek.Saturday;
}
private static bool IsValidKeyboardSelection(Calendar cal, object value)
{
if (value == null)
{
return true;
}
else
{
if (cal.BlackoutDates.Contains((DateTime)value))
{
return false;
}
else
{
return DateTime.Compare((DateTime)value, cal.DisplayDateStartInternal) >= 0 && DateTime.Compare((DateTime)value, cal.DisplayDateEndInternal) <= 0;
}
}
}
private static bool IsValidSelectionMode(object value)
{
CalendarSelectionMode mode = (CalendarSelectionMode)value;
return mode == CalendarSelectionMode.SingleDate
|| mode == CalendarSelectionMode.SingleRange
|| mode == CalendarSelectionMode.MultipleRange
|| mode == CalendarSelectionMode.None;
}
private void OnSelectedMonthChanged(DateTime? selectedMonth)
{
if (selectedMonth.HasValue)
{
Debug.Assert(this.DisplayMode == CalendarMode.Year);
this.DisplayDate = selectedMonth.Value;
UpdateCellItems();
FocusDate(selectedMonth.Value);
}
}
private void OnSelectedYearChanged(DateTime? selectedYear)
{
if (selectedYear.HasValue)
{
Debug.Assert(this.DisplayMode == CalendarMode.Decade);
this.DisplayDate = selectedYear.Value;
UpdateCellItems();
FocusDate(selectedYear.Value);
}
}
internal void FocusDate(DateTime date)
{
if (MonthControl != null)
{
MonthControl.FocusDate(date);
}
}
///
/// Called when this element gets focus.
///
private static void OnGotFocus(object sender, RoutedEventArgs e)
{
// When Calendar gets focus move it to the DisplayDate
var c = (Calendar)sender;
if (!e.Handled && e.OriginalSource == c)
{
// This check is for the case where the DisplayDate is the first of the month
// and the SelectedDate is in the middle of the month. If you tab into the Calendar
// the focus should go to the SelectedDate, not the DisplayDate.
if (c.SelectedDate.HasValue && DateTimeHelper.CompareYearMonth(c.SelectedDate.Value, c.DisplayDateInternal) == 0)
{
c.FocusDate(c.SelectedDate.Value);
}
else
{
c.FocusDate(c.DisplayDate);
}
e.Handled = true;
}
}
private bool ProcessCalendarKey(KeyEventArgs e)
{
if (this.DisplayMode == CalendarMode.Month)
{
// If a blackout day is inactive, when clicked on it, the previous inactive day which is not a blackout day can get the focus.
// In this case we should allow keyboard functions on that inactive day
CalendarDayButton currentDayButton = (MonthControl != null) ? MonthControl.GetCalendarDayButton(this.CurrentDate) : null;
if (DateTimeHelper.CompareYearMonth(this.CurrentDate, this.DisplayDateInternal) != 0 && currentDayButton != null && !currentDayButton.IsInactive)
{
return false;
}
}
bool ctrl, shift;
KeyboardHelper.GetMetaKeyState(out ctrl, out shift);
switch (e.Key)
{
case Key.Up:
{
ProcessUpKey(ctrl, shift);
return true;
}
case Key.Down:
{
ProcessDownKey(ctrl, shift);
return true;
}
case Key.Left:
{
ProcessLeftKey(shift);
return true;
}
case Key.Right:
{
ProcessRightKey(shift);
return true;
}
case Key.PageDown:
{
ProcessPageDownKey(shift);
return true;
}
case Key.PageUp:
{
ProcessPageUpKey(shift);
return true;
}
case Key.Home:
{
ProcessHomeKey(shift);
return true;
}
case Key.End:
{
ProcessEndKey(shift);
return true;
}
case Key.Enter:
case Key.Space:
{
return ProcessEnterKey();
}
}
return false;
}
private void ProcessDownKey(bool ctrl, bool shift)
{
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
if (!ctrl || shift)
{
DateTime? selectedDate = this._blackoutDates.GetNonBlackoutDate(DateTimeHelper.AddDays(this.CurrentDate, COLS), 1);
ProcessSelection(shift, selectedDate);
}
break;
}
case CalendarMode.Year:
{
if (ctrl)
{
this.DisplayMode = CalendarMode.Month;
FocusDate(this.DisplayDate);
}
else
{
DateTime? selectedMonth = DateTimeHelper.AddMonths(this.DisplayDate, YEAR_COLS);
OnSelectedMonthChanged(selectedMonth);
}
break;
}
case CalendarMode.Decade:
{
if (ctrl)
{
this.DisplayMode = CalendarMode.Year;
FocusDate(this.DisplayDate);
}
else
{
DateTime? selectedYear = DateTimeHelper.AddYears(this.DisplayDate, YEAR_COLS);
OnSelectedYearChanged(selectedYear);
}
break;
}
}
}
private void ProcessEndKey(bool shift)
{
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
if (this.DisplayDate != null)
{
DateTime? selectedDate = new DateTime(this.DisplayDateInternal.Year, this.DisplayDateInternal.Month, 1);
if (DateTimeHelper.CompareYearMonth(DateTime.MaxValue, selectedDate.Value) > 0)
{
// since DisplayDate is not equal to DateTime.MaxValue we are sure selectedDate is not null
selectedDate = DateTimeHelper.AddMonths(selectedDate.Value, 1).Value;
selectedDate = DateTimeHelper.AddDays(selectedDate.Value, -1).Value;
}
else
{
selectedDate = DateTime.MaxValue;
}
ProcessSelection(shift, selectedDate);
}
break;
}
case CalendarMode.Year:
{
DateTime selectedMonth = new DateTime(this.DisplayDate.Year, 12, 1);
OnSelectedMonthChanged(selectedMonth);
break;
}
case CalendarMode.Decade:
{
DateTime? selectedYear = new DateTime(DateTimeHelper.EndOfDecade(this.DisplayDate), 1, 1);
OnSelectedYearChanged(selectedYear);
break;
}
}
}
private bool ProcessEnterKey()
{
switch (this.DisplayMode)
{
case CalendarMode.Year:
{
this.DisplayMode = CalendarMode.Month;
FocusDate(this.DisplayDate);
return true;
}
case CalendarMode.Decade:
{
this.DisplayMode = CalendarMode.Year;
FocusDate(this.DisplayDate);
return true;
}
}
return false;
}
private void ProcessHomeKey(bool shift)
{
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
// TODO: Not all types of calendars start with Day1. If Non-Gregorian is supported check this:
DateTime? selectedDate = new DateTime(this.DisplayDateInternal.Year, this.DisplayDateInternal.Month, 1);
ProcessSelection(shift, selectedDate);
break;
}
case CalendarMode.Year:
{
DateTime selectedMonth = new DateTime(this.DisplayDate.Year, 1, 1);
OnSelectedMonthChanged(selectedMonth);
break;
}
case CalendarMode.Decade:
{
DateTime? selectedYear = new DateTime(DateTimeHelper.DecadeOfDate(this.DisplayDate), 1, 1);
OnSelectedYearChanged(selectedYear);
break;
}
}
}
private void ProcessLeftKey(bool shift)
{
int moveAmmount = (!this.IsRightToLeft) ? -1 : 1;
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
DateTime? selectedDate = this._blackoutDates.GetNonBlackoutDate(DateTimeHelper.AddDays(this.CurrentDate, moveAmmount), moveAmmount);
ProcessSelection(shift, selectedDate);
break;
}
case CalendarMode.Year:
{
DateTime? selectedMonth = DateTimeHelper.AddMonths(this.DisplayDate, moveAmmount);
OnSelectedMonthChanged(selectedMonth);
break;
}
case CalendarMode.Decade:
{
DateTime? selectedYear = DateTimeHelper.AddYears(this.DisplayDate, moveAmmount);
OnSelectedYearChanged(selectedYear);
break;
}
}
}
private void ProcessPageDownKey(bool shift)
{
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
DateTime? selectedDate = this._blackoutDates.GetNonBlackoutDate(DateTimeHelper.AddMonths(this.CurrentDate, 1), 1);
ProcessSelection(shift, selectedDate);
break;
}
case CalendarMode.Year:
{
DateTime? selectedMonth = DateTimeHelper.AddYears(this.DisplayDate, 1);
OnSelectedMonthChanged(selectedMonth);
break;
}
case CalendarMode.Decade:
{
DateTime? selectedYear = DateTimeHelper.AddYears(this.DisplayDate, 10);
OnSelectedYearChanged(selectedYear);
break;
}
}
}
private void ProcessPageUpKey(bool shift)
{
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
DateTime? selectedDate = this._blackoutDates.GetNonBlackoutDate(DateTimeHelper.AddMonths(this.CurrentDate, -1), -1);
ProcessSelection(shift, selectedDate);
break;
}
case CalendarMode.Year:
{
DateTime? selectedMonth = DateTimeHelper.AddYears(this.DisplayDate, -1);
OnSelectedMonthChanged(selectedMonth);
break;
}
case CalendarMode.Decade:
{
DateTime? selectedYear = DateTimeHelper.AddYears(this.DisplayDate, -10);
OnSelectedYearChanged(selectedYear);
break;
}
}
}
private void ProcessRightKey(bool shift)
{
int moveAmmount = (!this.IsRightToLeft) ? 1 : -1;
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
DateTime? selectedDate = this._blackoutDates.GetNonBlackoutDate(DateTimeHelper.AddDays(this.CurrentDate, moveAmmount), moveAmmount);
ProcessSelection(shift, selectedDate);
break;
}
case CalendarMode.Year:
{
DateTime? selectedMonth = DateTimeHelper.AddMonths(this.DisplayDate, moveAmmount);
OnSelectedMonthChanged(selectedMonth);
break;
}
case CalendarMode.Decade:
{
DateTime? selectedYear = DateTimeHelper.AddYears(this.DisplayDate, moveAmmount);
OnSelectedYearChanged(selectedYear);
break;
}
}
}
private void ProcessSelection(bool shift, DateTime? lastSelectedDate)
{
if (this.SelectionMode == CalendarSelectionMode.None && lastSelectedDate != null)
{
OnDayClick(lastSelectedDate.Value);
return;
}
if (lastSelectedDate != null && IsValidKeyboardSelection(this, lastSelectedDate.Value))
{
if (this.SelectionMode == CalendarSelectionMode.SingleRange || this.SelectionMode == CalendarSelectionMode.MultipleRange)
{
this.SelectedDates.ClearInternal();
if (shift)
{
this._isShiftPressed = true;
if (!this.HoverStart.HasValue)
{
this.HoverStart = this.HoverEnd = this.CurrentDate;
}
// If we hit a BlackOutDay with keyboard we do not update the HoverEnd
CalendarDateRange range;
if (DateTime.Compare(this.HoverStart.Value, lastSelectedDate.Value) < 0)
{
range = new CalendarDateRange(this.HoverStart.Value, lastSelectedDate.Value);
}
else
{
range = new CalendarDateRange(lastSelectedDate.Value, this.HoverStart.Value);
}
if (!this.BlackoutDates.ContainsAny(range))
{
this._currentDate = lastSelectedDate;
this.HoverEnd = lastSelectedDate;
}
OnDayClick(this.CurrentDate);
}
else
{
this.HoverStart = this.HoverEnd = this.CurrentDate = lastSelectedDate.Value;
AddKeyboardSelection();
OnDayClick(lastSelectedDate.Value);
}
}
else
{
// ON CLEAR
this.CurrentDate = lastSelectedDate.Value;
this.HoverStart = this.HoverEnd = null;
if (this.SelectedDates.Count > 0)
{
this.SelectedDates[0] = lastSelectedDate.Value;
}
else
{
this.SelectedDates.Add(lastSelectedDate.Value);
}
OnDayClick(lastSelectedDate.Value);
}
UpdateCellItems();
}
}
private void ProcessShiftKeyUp()
{
if (this._isShiftPressed && (this.SelectionMode == CalendarSelectionMode.SingleRange || this.SelectionMode == CalendarSelectionMode.MultipleRange))
{
AddKeyboardSelection();
this._isShiftPressed = false;
this.HoverStart = this.HoverEnd = null;
}
}
private void ProcessUpKey(bool ctrl, bool shift)
{
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
if (ctrl)
{
this.DisplayMode = CalendarMode.Year;
FocusDate(this.DisplayDate);
}
else
{
DateTime? selectedDate = this._blackoutDates.GetNonBlackoutDate(DateTimeHelper.AddDays(this.CurrentDate, -COLS), -1);
ProcessSelection(shift, selectedDate);
}
break;
}
case CalendarMode.Year:
{
if (ctrl)
{
this.DisplayMode = CalendarMode.Decade;
FocusDate(this.DisplayDate);
}
else
{
DateTime? selectedMonth = DateTimeHelper.AddMonths(this.DisplayDate, -YEAR_COLS);
OnSelectedMonthChanged(selectedMonth);
}
break;
}
case CalendarMode.Decade:
{
if (!ctrl)
{
DateTime? selectedYear = DateTimeHelper.AddYears(this.DisplayDate, -YEAR_COLS);
OnSelectedYearChanged(selectedYear);
}
break;
}
}
}
#endregion Private Methods
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Controls/CalendarBlackoutDatesCollection.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
namespace Microsoft.Windows.Controls
{
///
/// Represents a collection of DateTimeRanges.
///
public sealed class CalendarBlackoutDatesCollection : ObservableCollection
{
#region Data
private Thread _dispatcherThread;
private Calendar _owner;
#endregion Data
///
/// Initializes a new instance of the CalendarBlackoutDatesCollection class.
///
///
public CalendarBlackoutDatesCollection(Calendar owner)
{
_owner = owner;
this._dispatcherThread = Thread.CurrentThread;
}
#region Public Methods
///
/// Dates that are in the past are added to the BlackoutDates.
///
public void AddDatesInPast()
{
this.Add(new CalendarDateRange(DateTime.MinValue, DateTime.Today.AddDays(-1)));
}
///
/// Checks if a DateTime is in the Collection
///
///
///
public bool Contains(DateTime date)
{
return null != GetContainingDateRange(date);
}
///
/// Checks if a Range is in the collection
///
///
///
///
public bool Contains(DateTime start, DateTime end)
{
DateTime rangeStart, rangeEnd;
int n = Count;
if (DateTime.Compare(end, start) > -1)
{
rangeStart = DateTimeHelper.DiscardTime(start).Value;
rangeEnd = DateTimeHelper.DiscardTime(end).Value;
}
else
{
rangeStart = DateTimeHelper.DiscardTime(end).Value;
rangeEnd = DateTimeHelper.DiscardTime(start).Value;
}
for (int i = 0; i < n; i++)
{
if (DateTime.Compare(this[i].Start, rangeStart) == 0 && DateTime.Compare(this[i].End, rangeEnd) == 0)
{
return true;
}
}
return false;
}
///
/// Returns true if any day in the given DateTime range is contained in the BlackOutDays.
///
/// CalendarDateRange that is searched in BlackOutDays
/// true if at least one day in the range is included in the BlackOutDays
public bool ContainsAny(CalendarDateRange range)
{
foreach (CalendarDateRange item in this)
{
if (item.ContainsAny(range))
{
return true;
}
}
return false;
}
///
/// This finds the next date that is not blacked out in a certian direction.
///
///
///
///
internal DateTime? GetNonBlackoutDate(DateTime? requestedDate, int dayInterval)
{
Debug.Assert(dayInterval != 0);
DateTime? currentDate = requestedDate;
CalendarDateRange range = null;
if (requestedDate == null)
{
return null;
}
if ((range = GetContainingDateRange((DateTime)currentDate)) == null)
{
return requestedDate;
}
do
{
if (dayInterval > 0)
{
// Moving Forwards.
// The DateRanges require start <= end
currentDate = DateTimeHelper.AddDays(range.End, dayInterval);
}
else
{
//Moving backwards.
currentDate = DateTimeHelper.AddDays(range.Start, dayInterval);
}
} while (currentDate != null && ((range = GetContainingDateRange((DateTime)currentDate)) != null));
return currentDate;
}
#endregion Public Methods
#region Protected Methods
///
/// All the items in the collection are removed.
///
protected override void ClearItems()
{
if (!IsValidThread())
{
throw new NotSupportedException(SR.Get(SRID.CalendarCollection_MultiThreadedCollectionChangeNotSupported));
}
foreach (CalendarDateRange item in Items)
{
UnRegisterItem(item);
}
base.ClearItems();
this._owner.UpdateCellItems();
}
///
/// The item is inserted in the specified place in the collection.
///
///
///
protected override void InsertItem(int index, CalendarDateRange item)
{
if (!IsValidThread())
{
throw new NotSupportedException(SR.Get(SRID.CalendarCollection_MultiThreadedCollectionChangeNotSupported));
}
if (IsValid(item))
{
RegisterItem(item);
base.InsertItem(index, item);
_owner.UpdateCellItems();
}
else
{
throw new ArgumentOutOfRangeException(SR.Get(SRID.Calendar_UnSelectableDates));
}
}
///
/// The item in the specified index is removed from the collection.
///
///
protected override void RemoveItem(int index)
{
if (!IsValidThread())
{
throw new NotSupportedException(SR.Get(SRID.CalendarCollection_MultiThreadedCollectionChangeNotSupported));
}
if (index >= 0 && index < this.Count)
{
UnRegisterItem(Items[index]);
}
base.RemoveItem(index);
_owner.UpdateCellItems();
}
///
/// The object in the specified index is replaced with the provided item.
///
///
///
protected override void SetItem(int index, CalendarDateRange item)
{
if (!IsValidThread())
{
throw new NotSupportedException(SR.Get(SRID.CalendarCollection_MultiThreadedCollectionChangeNotSupported));
}
if (IsValid(item))
{
CalendarDateRange oldItem = null;
if (index >= 0 && index < this.Count)
{
oldItem = Items[index];
}
base.SetItem(index, item);
UnRegisterItem(oldItem);
RegisterItem(Items[index]);
_owner.UpdateCellItems();
}
else
{
throw new ArgumentOutOfRangeException(SR.Get(SRID.Calendar_UnSelectableDates));
}
}
#endregion Protected Methods
#region Private Methods
///
/// Registers for change notification on date ranges
///
///
private void RegisterItem(CalendarDateRange item)
{
if (item != null)
{
item.Changing += new EventHandler(Item_Changing);
item.PropertyChanged += new PropertyChangedEventHandler(Item_PropertyChanged);
}
}
///
/// Un registers for change notification on date ranges
///
private void UnRegisterItem(CalendarDateRange item)
{
if (item != null)
{
item.Changing -= new EventHandler(Item_Changing);
item.PropertyChanged -= new PropertyChangedEventHandler(Item_PropertyChanged);
}
}
///
/// Reject date range changes that would make the blackout dates collection invalid
///
///
///
private void Item_Changing(object sender, CalendarDateRangeChangingEventArgs e)
{
CalendarDateRange item = sender as CalendarDateRange;
if (item != null)
{
if (!IsValid(e.Start, e.End))
{
throw new ArgumentOutOfRangeException(SR.Get(SRID.Calendar_UnSelectableDates));
}
}
}
///
/// Update the calendar view to reflect the new blackout dates
///
///
///
private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (sender is CalendarDateRange)
{
_owner.UpdateCellItems();
}
}
///
/// Tests to see if a date range is not already selected
///
/// date range to test
/// True if no selected day falls in the given date range
private bool IsValid(CalendarDateRange item)
{
return IsValid(item.Start, item.End);
}
///
/// Tests to see if a date range is not already selected
///
/// First day of date range to test
/// Last day of date range to test
/// True if no selected day falls between start and end
private bool IsValid(DateTime start, DateTime end)
{
foreach (object child in _owner.SelectedDates)
{
DateTime? day = child as DateTime?;
Debug.Assert(day != null);
if (DateTimeHelper.InRange(day.Value, start, end))
{
return false;
}
}
return true;
}
private bool IsValidThread()
{
return Thread.CurrentThread == this._dispatcherThread;
}
///
/// Gets the DateRange that contains the date.
///
///
///
private CalendarDateRange GetContainingDateRange(DateTime date)
{
if (date == null)
return null;
for (int i = 0; i < Count; i++)
{
if (DateTimeHelper.InRange(date, this[i]))
{
return this[i];
}
}
return null;
}
#endregion Private Methods
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Controls/CalendarButton.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Controls;
using System.Windows.Data;
using Microsoft.Windows.Automation.Peers;
namespace Microsoft.Windows.Controls.Primitives
{
///
/// Represents a button control used in Calendar Control, which reacts to the Click event.
///
[TemplateVisualState(Name = VisualStates.StateNormal, GroupName = VisualStates.GroupCommon)]
[TemplateVisualState(Name = VisualStates.StateMouseOver, GroupName = VisualStates.GroupCommon)]
[TemplateVisualState(Name = VisualStates.StatePressed, GroupName = VisualStates.GroupCommon)]
[TemplateVisualState(Name = VisualStates.StateDisabled, GroupName = VisualStates.GroupCommon)]
[TemplateVisualState(Name = VisualStates.StateUnselected, GroupName = VisualStates.GroupSelection)]
[TemplateVisualState(Name = VisualStates.StateSelected, GroupName = VisualStates.GroupSelection)]
[TemplateVisualState(Name = VisualStates.StateCalendarButtonUnfocused, GroupName = VisualStates.GroupCalendarButtonFocus)]
[TemplateVisualState(Name = VisualStates.StateCalendarButtonFocused, GroupName = VisualStates.GroupCalendarButtonFocus)]
[TemplateVisualState(Name = VisualStates.StateInactive, GroupName = VisualStates.GroupActive)]
[TemplateVisualState(Name = VisualStates.StateActive, GroupName = VisualStates.GroupActive)]
public sealed class CalendarButton : Button
{
#region Data
private bool _shouldCoerceContent;
private object _coercedContent;
#endregion Data
///
/// Static constructor
///
static CalendarButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CalendarButton), new FrameworkPropertyMetadata(typeof(CalendarButton)));
ContentProperty.OverrideMetadata(typeof(CalendarButton), new FrameworkPropertyMetadata(null, OnCoerceContent));
}
///
/// Represents the CalendarButton that is used in Calendar Control.
///
public CalendarButton()
: base()
{
// Attach the necessary events to their virtual counterparts
Loaded += delegate { ChangeVisualState(false); };
}
#region Public Properties
#region HasSelectedDays
internal static readonly DependencyPropertyKey HasSelectedDaysPropertyKey = DependencyProperty.RegisterReadOnly(
"HasSelectedDays",
typeof(bool),
typeof(CalendarButton),
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnVisualStatePropertyChanged)));
///
/// Dependency property field for HasSelectedDays property
///
public static readonly DependencyProperty HasSelectedDaysProperty = HasSelectedDaysPropertyKey.DependencyProperty;
///
/// True if the CalendarButton represents a date range containing the display date
///
public bool HasSelectedDays
{
get { return (bool)GetValue(HasSelectedDaysProperty); }
internal set { SetValue(HasSelectedDaysPropertyKey, value); }
}
#endregion HasSelectedDays
#region IsInactive
internal static readonly DependencyPropertyKey IsInactivePropertyKey = DependencyProperty.RegisterReadOnly(
"IsInactive",
typeof(bool),
typeof(CalendarButton),
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnVisualStatePropertyChanged)));
///
/// Dependency property field for IsInactive property
///
public static readonly DependencyProperty IsInactiveProperty = IsInactivePropertyKey.DependencyProperty;
///
/// True if the CalendarButton represents
/// a month that falls outside the current year
/// or
/// a year that falls outside the current decade
///
public bool IsInactive
{
get { return (bool)GetValue(IsInactiveProperty); }
internal set { SetValue(IsInactivePropertyKey, value); }
}
#endregion IsInactive
#endregion Public Properties
#region Internal Properties
internal Microsoft.Windows.Controls.Calendar Owner
{
get;
set;
}
#endregion Internal Properties
#region Public Methods
///
/// Apply a template to the button.
///
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
// Sync the logical and visual states of the control
ChangeVisualState(false);
}
#endregion Public Methods
#region Protected Methods
///
/// Creates the automation peer for the DayButton.
///
///
protected override AutomationPeer OnCreateAutomationPeer()
{
return new CalendarButtonAutomationPeer(this);
}
protected override void OnGotKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
ChangeVisualState(true);
base.OnGotKeyboardFocus(e);
}
protected override void OnLostKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
ChangeVisualState(true);
base.OnLostKeyboardFocus(e);
}
#endregion Protected Methods
#region Internal Methods
internal void SetContentInternal(string value)
{
if (BindingOperations.GetBindingExpressionBase(this, ContentControl.ContentProperty) != null)
{
Content = value;
}
else
{
this._shouldCoerceContent = true;
this._coercedContent = value;
this.CoerceValue(ContentControl.ContentProperty);
}
}
#endregion
#region Private Methods
///
/// Change to the correct visual state for the button.
///
///
/// true to use transitions when updating the visual state, false to
/// snap directly to the new visual state.
///
private void ChangeVisualState(bool useTransitions)
{
// Update the SelectionStates group
if (HasSelectedDays)
{
VisualStates.GoToState(this, useTransitions, VisualStates.StateSelected, VisualStates.StateUnselected);
}
else
{
VisualStates.GoToState(this, useTransitions, VisualStates.StateUnselected);
}
// Update the ActiveStates group
if (IsInactive)
{
VisualStates.GoToState(this, useTransitions, VisualStates.StateInactive);
}
else
{
VisualStates.GoToState(this, useTransitions, VisualStates.StateActive, VisualStates.StateInactive);
}
// Update the FocusStates group
if (IsKeyboardFocused)
{
VisualStates.GoToState(this, useTransitions, VisualStates.StateCalendarButtonFocused, VisualStates.StateCalendarButtonUnfocused);
}
else
{
VisualStateManager.GoToState(this, VisualStates.StateCalendarButtonUnfocused, useTransitions);
}
}
///
/// Common PropertyChangedCallback for dependency properties that trigger visual state changes
///
///
///
private static void OnVisualStatePropertyChanged(DependencyObject dObject, DependencyPropertyChangedEventArgs e)
{
CalendarButton button = dObject as CalendarButton;
if (button != null && !object.Equals(e.OldValue, e.NewValue))
{
button.ChangeVisualState(true);
}
}
private static object OnCoerceContent(DependencyObject sender, object baseValue)
{
CalendarButton button = (CalendarButton)sender;
if (button._shouldCoerceContent)
{
button._shouldCoerceContent = false;
return button._coercedContent;
}
return baseValue;
}
#endregion Private Methods
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Controls/CalendarDateChangedEventArgs.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
namespace Microsoft.Windows.Controls
{
///
/// Provides data for the DateSelected and DisplayDateChanged events.
///
public class CalendarDateChangedEventArgs : System.Windows.RoutedEventArgs
{
internal CalendarDateChangedEventArgs(DateTime? removedDate, DateTime? addedDate)
{
this.RemovedDate = removedDate;
this.AddedDate = addedDate;
}
///
/// Gets the date to be newly displayed.
///
public DateTime? AddedDate
{
get;
private set;
}
///
/// Gets the date that was previously displayed.
///
public DateTime? RemovedDate
{
get;
private set;
}
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Controls/CalendarDateRange.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.ComponentModel;
namespace Microsoft.Windows.Controls
{
///
/// Specifies a DateTime range class which has a start and end.
///
public sealed class CalendarDateRange : INotifyPropertyChanged
{
#region Data
private DateTime _end;
private DateTime _start;
#endregion Data
///
/// Initializes a new instance of the CalendarDateRange class.
///
public CalendarDateRange() :
this(DateTime.MinValue, DateTime.MaxValue)
{
}
///
/// Initializes a new instance of the CalendarDateRange class which creates a range from a single DateTime value.
///
///
public CalendarDateRange(DateTime day) :
this(day, day)
{
}
///
/// Initializes a new instance of the CalendarDateRange class which accepts range start and end dates.
///
///
///
public CalendarDateRange(DateTime start, DateTime end)
{
_start = start;
_end = end;
}
#region Public Events
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region Public Properties
///
/// Specifies the End date of the CalendarDateRange.
///
public DateTime End
{
get
{
return CoerceEnd(_start, _end);
}
set
{
DateTime newEnd = CoerceEnd(_start, value);
if (newEnd != End)
{
OnChanging(new CalendarDateRangeChangingEventArgs(_start, newEnd));
_end = value;
OnPropertyChanged(new PropertyChangedEventArgs("End"));
}
}
}
///
/// Specifies the Start date of the CalendarDateRange.
///
public DateTime Start
{
get
{
return _start;
}
set
{
if (_start != value)
{
DateTime oldEnd = End;
DateTime newEnd = CoerceEnd(value, _end);
OnChanging(new CalendarDateRangeChangingEventArgs(value, newEnd));
_start = value;
OnPropertyChanged(new PropertyChangedEventArgs("Start"));
if (newEnd != oldEnd)
{
OnPropertyChanged(new PropertyChangedEventArgs("End"));
}
}
}
}
#endregion Public Properties
#region Internal Events
internal event EventHandler Changing;
#endregion Internal Events
#region Internal Methods
///
/// Returns true if any day in the given DateTime range is contained in the current CalendarDateRange.
///
///
///
internal bool ContainsAny(CalendarDateRange range)
{
return (range.End >= this.Start) && (this.End >= range.Start);
}
#endregion Internal Methods
#region Private Methods
private void OnChanging(CalendarDateRangeChangingEventArgs e)
{
EventHandler handler = this.Changing;
if (handler != null)
{
handler(this, e);
}
}
private void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, e);
}
}
///
/// Coerced the end parameter to satisfy the start <= end constraint
///
///
///
/// If start <= end the end parameter otherwise the start parameter
private static DateTime CoerceEnd(DateTime start, DateTime end)
{
return (DateTime.Compare(start, end) <= 0) ? end : start;
}
#endregion Private Methods
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Controls/CalendarDateRangeChangingEventArgs.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
namespace Microsoft.Windows.Controls
{
///
/// Event arguments to notify clients that the range is changing and what the new range will be
///
internal class CalendarDateRangeChangingEventArgs : EventArgs
{
public CalendarDateRangeChangingEventArgs(DateTime start, DateTime end)
{
_start = start;
_end = end;
}
public DateTime Start
{
get { return _start; }
}
public DateTime End
{
get { return _end; }
}
private DateTime _start;
private DateTime _end;
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Controls/CalendarDayButton.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Controls;
using System.Windows.Data;
using Microsoft.Windows.Automation.Peers;
namespace Microsoft.Windows.Controls.Primitives
{
///
/// Represents a button control used in Calendar Control, which reacts to the Click event.
///
[TemplateVisualState(Name = VisualStates.StateNormal, GroupName = VisualStates.GroupCommon)]
[TemplateVisualState(Name = VisualStates.StateMouseOver, GroupName = VisualStates.GroupCommon)]
[TemplateVisualState(Name = VisualStates.StatePressed, GroupName = VisualStates.GroupCommon)]
[TemplateVisualState(Name = VisualStates.StateDisabled, GroupName = VisualStates.GroupCommon)]
[TemplateVisualState(Name = VisualStates.StateUnselected, GroupName = VisualStates.GroupSelection)]
[TemplateVisualState(Name = VisualStates.StateSelected, GroupName = VisualStates.GroupSelection)]
[TemplateVisualState(Name = VisualStates.StateCalendarButtonUnfocused, GroupName = VisualStates.GroupCalendarButtonFocus)]
[TemplateVisualState(Name = VisualStates.StateCalendarButtonFocused, GroupName = VisualStates.GroupCalendarButtonFocus)]
[TemplateVisualState(Name = VisualStates.StateInactive, GroupName = VisualStates.GroupActive)]
[TemplateVisualState(Name = VisualStates.StateActive, GroupName = VisualStates.GroupActive)]
[TemplateVisualState(Name = CalendarDayButton.StateRegularDay, GroupName = CalendarDayButton.GroupDay)]
[TemplateVisualState(Name = CalendarDayButton.StateToday, GroupName = CalendarDayButton.GroupDay)]
[TemplateVisualState(Name = CalendarDayButton.StateNormalDay, GroupName = CalendarDayButton.GroupBlackout)]
[TemplateVisualState(Name = CalendarDayButton.StateBlackoutDay, GroupName = CalendarDayButton.GroupBlackout)]
public sealed class CalendarDayButton : Button
{
#region Constants
///
/// Default content for the CalendarDayButton
///
private const int DEFAULTCONTENT = 1;
///
/// Identifies the Today state.
///
internal const string StateToday = "Today";
///
/// Identifies the RegularDay state.
///
internal const string StateRegularDay = "RegularDay";
///
/// Name of the Day state group.
///
internal const string GroupDay = "DayStates";
///
/// Identifies the BlackoutDay state.
///
internal const string StateBlackoutDay = "BlackoutDay";
///
/// Identifies the NormalDay state.
///
internal const string StateNormalDay = "NormalDay";
///
/// Name of the BlackoutDay state group.
///
internal const string GroupBlackout = "BlackoutDayStates";
#endregion Constants
#region Data
private bool _shouldCoerceContent;
private object _coercedContent;
#endregion Data
///
/// Static constructor
///
static CalendarDayButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CalendarDayButton), new FrameworkPropertyMetadata(typeof(CalendarDayButton)));
ContentProperty.OverrideMetadata(typeof(CalendarDayButton), new FrameworkPropertyMetadata(null, OnCoerceContent));
}
///
/// Represents the CalendarDayButton that is used in Calendar Control.
///
public CalendarDayButton()
: base()
{
// Attach the necessary events to their virtual counterparts
Loaded += delegate { ChangeVisualState(false); };
}
#region Public Properties
#region IsToday
internal static readonly DependencyPropertyKey IsTodayPropertyKey = DependencyProperty.RegisterReadOnly(
"IsToday",
typeof(bool),
typeof(CalendarDayButton),
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnVisualStatePropertyChanged)));
///
/// Dependency property field for IsToday property
///
public static readonly DependencyProperty IsTodayProperty = IsTodayPropertyKey.DependencyProperty;
///
/// True if the CalendarDayButton represents today
///
public bool IsToday
{
get { return (bool)GetValue(IsTodayProperty); }
}
#endregion IsToday
#region IsSelected
internal static readonly DependencyPropertyKey IsSelectedPropertyKey = DependencyProperty.RegisterReadOnly(
"IsSelected",
typeof(bool),
typeof(CalendarDayButton),
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnVisualStatePropertyChanged)));
///
/// Dependency property field for IsSelected property
///
public static readonly DependencyProperty IsSelectedProperty = IsSelectedPropertyKey.DependencyProperty;
///
/// True if the CalendarDayButton is selected
///
public bool IsSelected
{
get { return (bool)GetValue(IsSelectedProperty); }
}
#endregion IsSelected
#region IsInactive
internal static readonly DependencyPropertyKey IsInactivePropertyKey = DependencyProperty.RegisterReadOnly(
"IsInactive",
typeof(bool),
typeof(CalendarDayButton),
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnVisualStatePropertyChanged)));
///
/// Dependency property field for IsActive property
///
public static readonly DependencyProperty IsInactiveProperty = IsInactivePropertyKey.DependencyProperty;
///
/// True if the CalendarDayButton represents a day that falls in the currently displayed month
///
public bool IsInactive
{
get { return (bool)GetValue(IsInactiveProperty); }
}
#endregion IsInactive
#region IsBlackedOut
internal static readonly DependencyPropertyKey IsBlackedOutPropertyKey = DependencyProperty.RegisterReadOnly(
"IsBlackedOut",
typeof(bool),
typeof(CalendarDayButton),
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnVisualStatePropertyChanged)));
///
/// Dependency property field for IsBlackedOut property
///
public static readonly DependencyProperty IsBlackedOutProperty = IsBlackedOutPropertyKey.DependencyProperty;
///
/// True if the CalendarDayButton represents a blackout date
///
public bool IsBlackedOut
{
get { return (bool)GetValue(IsBlackedOutProperty); }
}
#endregion IsBlackedOut
#region IsHighlighted
internal static readonly DependencyPropertyKey IsHighlightedPropertyKey = DependencyProperty.RegisterReadOnly(
"IsHighlighted",
typeof(bool),
typeof(CalendarDayButton),
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnVisualStatePropertyChanged)));
///
/// Dependency property field for IsHighlighted property
///
public static readonly DependencyProperty IsHighlightedProperty = IsHighlightedPropertyKey.DependencyProperty;
///
/// True if the CalendarDayButton represents a highlighted date
///
public bool IsHighlighted
{
get { return (bool)GetValue(IsHighlightedProperty); }
}
#endregion IsHighlighted
#endregion Public Properties
#region Internal Properties
internal Microsoft.Windows.Controls.Calendar Owner
{
get;
set;
}
#endregion Internal Properties
#region Public Methods
///
/// Apply a template to the button.
///
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
// Sync the logical and visual states of the control
ChangeVisualState(false);
}
#endregion Public Methods
#region Protected Methods
///
/// Creates the automation peer for the CalendarDayButton.
///
///
protected override AutomationPeer OnCreateAutomationPeer()
{
return new CalendarDayButtonAutomationPeer(this);
}
protected override void OnGotKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
ChangeVisualState(true);
base.OnGotKeyboardFocus(e);
}
protected override void OnLostKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
ChangeVisualState(true);
base.OnLostKeyboardFocus(e);
}
#endregion Protected Methods
#region Internal Methods
///
/// Change to the correct visual state for the button.
///
///
/// true to use transitions when updating the visual state, false to
/// snap directly to the new visual state.
///
internal void ChangeVisualState(bool useTransitions)
{
if (this.IsEnabled)
{
VisualStates.GoToState(this, useTransitions, VisualStates.StateNormal);
}
else
{
VisualStates.GoToState(this, useTransitions, VisualStates.StateDisabled);
}
// Update the SelectionStates group
if (IsSelected || IsHighlighted)
{
VisualStates.GoToState(this, useTransitions, VisualStates.StateSelected, VisualStates.StateUnselected);
}
else
{
VisualStates.GoToState(this, useTransitions, VisualStates.StateUnselected);
}
// Update the ActiveStates group
if (!IsInactive)
{
VisualStates.GoToState(this, useTransitions, VisualStates.StateActive, VisualStates.StateInactive);
}
else
{
VisualStates.GoToState(this, useTransitions, VisualStates.StateInactive);
}
// Update the DayStates group
if (IsToday && this.Owner != null && this.Owner.IsTodayHighlighted)
{
VisualStates.GoToState(this, useTransitions, StateToday, StateRegularDay);
}
else
{
VisualStates.GoToState(this, useTransitions, StateRegularDay);
}
// Update the BlackoutDayStates group
if (IsBlackedOut)
{
VisualStates.GoToState(this, useTransitions, StateBlackoutDay, StateNormalDay);
}
else
{
VisualStates.GoToState(this, useTransitions, StateNormalDay);
}
// Update the FocusStates group
if (IsKeyboardFocused)
{
VisualStates.GoToState(this, useTransitions, VisualStates.StateCalendarButtonFocused, VisualStates.StateCalendarButtonUnfocused);
}
else
{
VisualStateManager.GoToState(this, VisualStates.StateCalendarButtonUnfocused, useTransitions);
}
}
internal void SetContentInternal(string value)
{
if (BindingOperations.GetBindingExpressionBase(this, ContentControl.ContentProperty) != null)
{
Content = value;
}
else
{
this._shouldCoerceContent = true;
this._coercedContent = value;
this.CoerceValue(ContentControl.ContentProperty);
}
}
#endregion Internal Methods
#region Private Methods
///
/// Common PropertyChangedCallback for dependency properties that trigger visual state changes
///
///
///
private static void OnVisualStatePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
CalendarDayButton dayButton = sender as CalendarDayButton;
if (dayButton != null)
{
dayButton.ChangeVisualState(true);
}
}
private static object OnCoerceContent(DependencyObject sender, object baseValue)
{
CalendarDayButton button = (CalendarDayButton)sender;
if (button._shouldCoerceContent)
{
button._shouldCoerceContent = false;
return button._coercedContent;
}
return baseValue;
}
#endregion Private Methods
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Controls/CalendarItem.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
namespace Microsoft.Windows.Controls.Primitives
{
[TemplatePart(Name = CalendarItem.ElementRoot, Type = typeof(FrameworkElement))]
[TemplatePart(Name = CalendarItem.ElementHeaderButton, Type = typeof(Button))]
[TemplatePart(Name = CalendarItem.ElementPreviousButton, Type = typeof(Button))]
[TemplatePart(Name = CalendarItem.ElementNextButton, Type = typeof(Button))]
[TemplatePart(Name = CalendarItem.ElementDayTitleTemplate, Type = typeof(DataTemplate))]
[TemplatePart(Name = CalendarItem.ElementMonthView, Type = typeof(Grid))]
[TemplatePart(Name = CalendarItem.ElementYearView, Type = typeof(Grid))]
[TemplatePart(Name = CalendarItem.ElementDisabledVisual, Type = typeof(FrameworkElement))]
[TemplateVisualState(Name = VisualStates.StateNormal, GroupName = VisualStates.GroupCommon)]
[TemplateVisualState(Name = VisualStates.StateDisabled, GroupName = VisualStates.GroupCommon)]
public sealed partial class CalendarItem : Control
{
#region Constants
private const string ElementRoot = "PART_Root";
private const string ElementHeaderButton = "PART_HeaderButton";
private const string ElementPreviousButton = "PART_PreviousButton";
private const string ElementNextButton = "PART_NextButton";
private const string ElementDayTitleTemplate = "DayTitleTemplate";
private const string ElementMonthView = "PART_MonthView";
private const string ElementYearView = "PART_YearView";
private const string ElementDisabledVisual = "PART_DisabledVisual";
private const int COLS = 7;
private const int ROWS = 7;
private const int YEAR_COLS = 4;
private const int YEAR_ROWS = 3;
private const int NUMBER_OF_DAYS_IN_WEEK = 7;
#endregion Constants
#region Data
private System.Globalization.Calendar _calendar = new GregorianCalendar();
private DataTemplate _dayTitleTemplate;
private FrameworkElement _disabledVisual;
private Button _headerButton;
private Grid _monthView;
private Button _nextButton;
private Button _previousButton;
private Grid _yearView;
private bool _isMonthPressed;
private bool _isDayPressed;
#endregion Data
static CalendarItem()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CalendarItem), new FrameworkPropertyMetadata(typeof(CalendarItem)));
FocusableProperty.OverrideMetadata(typeof(CalendarItem), new FrameworkPropertyMetadata(false));
KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(CalendarItem), new FrameworkPropertyMetadata(KeyboardNavigationMode.Once));
KeyboardNavigation.DirectionalNavigationProperty.OverrideMetadata(typeof(CalendarItem), new FrameworkPropertyMetadata(KeyboardNavigationMode.Contained));
}
///
/// Represents the month that is used in Calendar Control.
///
public CalendarItem()
{
}
#region Internal Properties
internal Grid MonthView
{
get { return _monthView; }
}
internal Microsoft.Windows.Controls.Calendar Owner
{
get;
set;
}
internal Grid YearView
{
get { return _yearView; }
}
#endregion Internal Properties
#region Private Properties
///
/// Gets a value indicating whether the calendar is displayed in months, years or decades.
///
private CalendarMode DisplayMode
{
get
{
return (this.Owner != null) ? this.Owner.DisplayMode : CalendarMode.Month;
}
}
private Button HeaderButton
{
get
{
return this._headerButton;
}
}
private Button NextButton
{
get
{
return this._nextButton;
}
}
private Button PreviousButton
{
get
{
return this._previousButton;
}
}
private DateTime DisplayDate
{
get
{
return (Owner != null) ? Owner.DisplayDate : DateTime.Today;
}
}
#endregion Private Properties
#region Public Methods
///
/// Invoked whenever application code or an internal process,
/// such as a rebuilding layout pass, calls the ApplyTemplate method.
///
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (this._previousButton != null)
{
this._previousButton.Click -= new RoutedEventHandler(PreviousButton_Click);
}
if (this._nextButton != null)
{
this._nextButton.Click -= new RoutedEventHandler(NextButton_Click);
}
if (this._headerButton != null)
{
this._headerButton.Click -= new RoutedEventHandler(HeaderButton_Click);
}
_monthView = GetTemplateChild(ElementMonthView) as Grid;
_yearView = GetTemplateChild(ElementYearView) as Grid;
_previousButton = GetTemplateChild(ElementPreviousButton) as Button;
_nextButton = GetTemplateChild(ElementNextButton) as Button;
_headerButton = GetTemplateChild(ElementHeaderButton) as Button;
_disabledVisual = GetTemplateChild(ElementDisabledVisual) as FrameworkElement;
// WPF Compat: Unlike SL, WPF is not able to get elements in template resources with GetTemplateChild()
_dayTitleTemplate = null;
if (Template != null && Template.Resources.Contains(ElementDayTitleTemplate))
{
_dayTitleTemplate = Template.Resources[ElementDayTitleTemplate] as DataTemplate;
}
if (this._previousButton != null)
{
// If the user does not provide a Content value in template, we provide a helper text that can be used in Accessibility
// this text is not shown on the UI, just used for Accessibility purposes
if (this._previousButton.Content == null)
{
this._previousButton.Content = SR.Get(SRID.Calendar_PreviousButtonName);
}
this._previousButton.Click += new RoutedEventHandler(PreviousButton_Click);
}
if (this._nextButton != null)
{
// If the user does not provide a Content value in template, we provide a helper text that can be used in Accessibility
// this text is not shown on the UI, just used for Accessibility purposes
if (this._nextButton.Content == null)
{
this._nextButton.Content = SR.Get(SRID.Calendar_NextButtonName);
}
this._nextButton.Click += new RoutedEventHandler(NextButton_Click);
}
if (this._headerButton != null)
{
this._headerButton.Click += new RoutedEventHandler(HeaderButton_Click);
}
PopulateGrids();
if (this.Owner != null)
{
switch (this.Owner.DisplayMode)
{
case CalendarMode.Year:
UpdateYearMode();
break;
case CalendarMode.Decade:
UpdateDecadeMode();
break;
case CalendarMode.Month:
UpdateMonthMode();
break;
default:
Debug.Assert(false);
break;
}
}
else
{
UpdateMonthMode();
}
}
#endregion Public Methods
#region Protected Methods
protected override void OnMouseUp(MouseButtonEventArgs e)
{
base.OnMouseUp(e);
if (this.IsMouseCaptured)
{
this.ReleaseMouseCapture();
}
this._isMonthPressed = false;
this._isDayPressed = false;
// In Month mode, we may need to end a drag selection even if the mouse up isn't on the calendar.
if (!e.Handled &&
this.Owner.DisplayMode == CalendarMode.Month &&
this.Owner.HoverEnd.HasValue)
{
FinishSelection(this.Owner.HoverEnd.Value);
}
}
protected override void OnLostMouseCapture(MouseEventArgs e)
{
base.OnLostMouseCapture(e);
if (!this.IsMouseCaptured)
{
this._isDayPressed = false;
this._isMonthPressed = false;
}
}
#endregion
#region Internal Methods
internal void UpdateDecadeMode()
{
DateTime selectedYear;
if (this.Owner != null)
{
selectedYear = this.Owner.DisplayYear;
}
else
{
selectedYear = DateTime.Today;
}
int decade = GetDecadeForDecadeMode(selectedYear);
int decadeEnd = decade + 9;
SetDecadeModeHeaderButton(decade);
SetDecadeModePreviousButton(decade);
SetDecadeModeNextButton(decadeEnd);
if (_yearView != null)
{
SetYearButtons(decade, decadeEnd);
}
}
internal void UpdateMonthMode()
{
SetMonthModeHeaderButton();
SetMonthModePreviousButton();
SetMonthModeNextButton();
if (_monthView != null)
{
SetMonthModeDayTitles();
SetMonthModeCalendarDayButtons();
AddMonthModeHighlight();
}
}
internal void UpdateYearMode()
{
SetYearModeHeaderButton();
SetYearModePreviousButton();
SetYearModeNextButton();
if (_yearView != null)
{
SetYearModeMonthButtons();
}
}
internal IEnumerable GetCalendarDayButtons()
{
// TODO: should be updated if we support MultiCalendar
int count = ROWS * COLS;
if (MonthView != null)
{
UIElementCollection dayButtonsHost = MonthView.Children;
for (int childIndex = COLS; childIndex < count; childIndex++)
{
CalendarDayButton b = dayButtonsHost[childIndex] as CalendarDayButton;
if (b != null)
{
yield return b;
}
}
}
}
internal CalendarDayButton GetFocusedCalendarDayButton()
{
foreach (CalendarDayButton b in GetCalendarDayButtons())
{
if (b != null && b.IsFocused)
{
return b;
}
}
return null;
}
internal CalendarDayButton GetCalendarDayButton(DateTime date)
{
foreach (CalendarDayButton b in GetCalendarDayButtons())
{
if (b != null && b.DataContext is DateTime)
{
if (DateTimeHelper.CompareDays(date, (DateTime)b.DataContext) == 0)
{
return b;
}
}
}
return null;
}
internal CalendarButton GetCalendarButton(DateTime date, CalendarMode mode)
{
Debug.Assert(mode != CalendarMode.Month);
foreach (CalendarButton b in GetCalendarButtons())
{
if (b != null && b.DataContext is DateTime)
{
if (mode == CalendarMode.Year)
{
if (DateTimeHelper.CompareYearMonth(date, (DateTime)b.DataContext) == 0)
{
return b;
}
}
else
{
if (date.Year == ((DateTime)b.DataContext).Year)
{
return b;
}
}
}
}
return null;
}
internal CalendarButton GetFocusedCalendarButton()
{
foreach (CalendarButton b in GetCalendarButtons())
{
if (b != null && b.IsFocused)
{
return b;
}
}
return null;
}
private IEnumerable GetCalendarButtons()
{
foreach (UIElement element in this.YearView.Children)
{
CalendarButton b = element as CalendarButton;
if (b != null)
{
yield return b;
}
}
}
internal void FocusDate(DateTime date)
{
FrameworkElement focusTarget = null;
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
focusTarget = GetCalendarDayButton(date);
break;
}
case CalendarMode.Year:
case CalendarMode.Decade:
{
focusTarget = GetCalendarButton(date, this.DisplayMode);
break;
}
default:
{
Debug.Assert(false);
break;
}
}
if (focusTarget != null && !focusTarget.IsFocused)
{
focusTarget.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
}
}
#endregion Internal Methods
#region Private Methods
private int GetDecadeForDecadeMode(DateTime selectedYear)
{
int decade = DateTimeHelper.DecadeOfDate(selectedYear);
// Adjust the decade value if the mouse move selection is on,
// such that if first or last year among the children are selected
// then return the current selected decade as is.
if (_isMonthPressed && _yearView != null)
{
UIElementCollection yearViewChildren = _yearView.Children;
int count = yearViewChildren.Count;
if (count > 0)
{
CalendarButton child = yearViewChildren[0] as CalendarButton;
if (child != null &&
child.DataContext is DateTime &&
((DateTime)child.DataContext).Year == selectedYear.Year)
{
return (decade + 10);
}
}
if (count > 1)
{
CalendarButton child = yearViewChildren[count - 1] as CalendarButton;
if (child != null &&
child.DataContext is DateTime &&
((DateTime)child.DataContext).Year == selectedYear.Year)
{
return (decade - 10);
}
}
}
return decade;
}
private void EndDrag(bool ctrl, DateTime selectedDate)
{
if (this.Owner != null)
{
this.Owner.CurrentDate = selectedDate;
if (this.Owner.HoverStart.HasValue)
{
if (
ctrl &&
DateTime.Compare(this.Owner.HoverStart.Value, selectedDate) == 0 &&
(Owner.SelectionMode == CalendarSelectionMode.SingleDate || Owner.SelectionMode == CalendarSelectionMode.MultipleRange))
{
// Ctrl + single click = toggle
this.Owner.SelectedDates.Toggle(selectedDate);
}
else
{
// this is selection with Mouse, we do not guarantee the range does not include BlackOutDates.
// Use the internal AddRange that omits BlackOutDates based on the SelectionMode
this.Owner.SelectedDates.AddRangeInternal(this.Owner.HoverStart.Value, selectedDate);
}
Owner.OnDayClick(selectedDate);
}
}
}
private void CellOrMonth_PreviewKeyDown(object sender, RoutedEventArgs e)
{
Debug.Assert(e != null);
if (this.Owner == null)
{
return;
}
this.Owner.OnDayOrMonthPreviewKeyDown(e);
}
private void Cell_Clicked(object sender, RoutedEventArgs e)
{
if (this.Owner == null)
{
return;
}
CalendarDayButton b = sender as CalendarDayButton;
Debug.Assert(b != null);
if (!(b.DataContext is DateTime))
{
return;
}
// If the day is a blackout day selection is not allowed
if (!b.IsBlackedOut)
{
DateTime clickedDate = (DateTime)b.DataContext;
bool ctrl, shift;
KeyboardHelper.GetMetaKeyState(out ctrl, out shift);
switch (this.Owner.SelectionMode)
{
case CalendarSelectionMode.None:
{
break;
}
case CalendarSelectionMode.SingleDate:
{
if (!ctrl)
{
this.Owner.SelectedDate = clickedDate;
}
else
{
this.Owner.SelectedDates.Toggle(clickedDate);
}
break;
}
case CalendarSelectionMode.SingleRange:
{
DateTime? lastDate = this.Owner.CurrentDate;
this.Owner.SelectedDates.ClearInternal(true /*fireChangeNotification*/);
if (shift && lastDate.HasValue)
{
this.Owner.SelectedDates.AddRangeInternal(lastDate.Value, clickedDate);
}
else
{
this.Owner.SelectedDate = clickedDate;
this.Owner.HoverStart = null;
this.Owner.HoverEnd = null;
}
break;
}
case CalendarSelectionMode.MultipleRange:
{
if (!ctrl)
{
this.Owner.SelectedDates.ClearInternal(true /*fireChangeNotification*/);
}
if (shift)
{
this.Owner.SelectedDates.AddRangeInternal(this.Owner.CurrentDate, clickedDate);
}
else
{
if (!ctrl)
{
this.Owner.SelectedDate = clickedDate;
}
else
{
this.Owner.SelectedDates.Toggle(clickedDate);
this.Owner.HoverStart = null;
this.Owner.HoverEnd = null;
}
}
break;
}
}
this.Owner.OnDayClick(clickedDate);
}
}
private void Cell_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
CalendarDayButton b = sender as CalendarDayButton;
if (b == null)
{
return;
}
if (this.Owner == null || !(b.DataContext is DateTime))
{
return;
}
if (b.IsBlackedOut)
{
this.Owner.HoverStart = null;
}
else
{
this._isDayPressed = true;
Mouse.Capture(this, CaptureMode.SubTree);
b.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
bool ctrl, shift;
KeyboardHelper.GetMetaKeyState(out ctrl, out shift);
DateTime selectedDate = (DateTime)b.DataContext;
Debug.Assert(selectedDate != null);
switch (this.Owner.SelectionMode)
{
case CalendarSelectionMode.None:
{
break;
}
case CalendarSelectionMode.SingleDate:
{
this.Owner.DatePickerDisplayDateFlag = true;
if (!ctrl)
{
this.Owner.SelectedDate = selectedDate;
}
else
{
this.Owner.SelectedDates.Toggle(selectedDate);
}
break;
}
case CalendarSelectionMode.SingleRange:
{
this.Owner.SelectedDates.ClearInternal();
if (shift)
{
if (!this.Owner.HoverStart.HasValue)
{
this.Owner.HoverStart = this.Owner.HoverEnd = this.Owner.CurrentDate;
}
}
else
{
this.Owner.HoverStart = this.Owner.HoverEnd = selectedDate;
}
break;
}
case CalendarSelectionMode.MultipleRange:
{
if (!ctrl)
{
this.Owner.SelectedDates.ClearInternal();
}
if (shift)
{
if (!this.Owner.HoverStart.HasValue)
{
this.Owner.HoverStart = this.Owner.HoverEnd = this.Owner.CurrentDate;
}
}
else
{
this.Owner.HoverStart = this.Owner.HoverEnd = selectedDate;
}
break;
}
}
this.Owner.CurrentDate = selectedDate;
this.Owner.UpdateCellItems();
}
}
private void Cell_MouseEnter(object sender, MouseEventArgs e)
{
CalendarDayButton b = sender as CalendarDayButton;
if (b == null)
{
return;
}
if (b.IsBlackedOut)
{
return;
}
if (e.LeftButton == MouseButtonState.Pressed && this._isDayPressed)
{
b.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
if (this.Owner == null || !(b.DataContext is DateTime))
{
return;
}
DateTime selectedDate = (DateTime)b.DataContext;
switch (this.Owner.SelectionMode)
{
case CalendarSelectionMode.SingleDate:
{
this.Owner.DatePickerDisplayDateFlag = true;
this.Owner.HoverStart = this.Owner.HoverEnd = null;
if (this.Owner.SelectedDates.Count == 0)
{
this.Owner.SelectedDates.Add(selectedDate);
}
else
{
this.Owner.SelectedDates[0] = selectedDate;
}
return;
}
}
this.Owner.HoverEnd = selectedDate;
this.Owner.CurrentDate = selectedDate;
this.Owner.UpdateCellItems();
}
}
private void Cell_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
CalendarDayButton b = sender as CalendarDayButton;
if (b == null)
{
return;
}
if (this.Owner == null)
{
return;
}
if (!b.IsBlackedOut)
{
this.Owner.OnDayButtonMouseUp(e);
}
if (!(b.DataContext is DateTime))
{
return;
}
FinishSelection((DateTime)b.DataContext);
e.Handled = true;
}
private void FinishSelection(DateTime selectedDate)
{
bool ctrl, shift;
KeyboardHelper.GetMetaKeyState(out ctrl, out shift);
if (this.Owner.SelectionMode == CalendarSelectionMode.None || this.Owner.SelectionMode == CalendarSelectionMode.SingleDate)
{
this.Owner.OnDayClick(selectedDate);
return;
}
if (this.Owner.HoverStart.HasValue)
{
switch (this.Owner.SelectionMode)
{
case CalendarSelectionMode.SingleRange:
{
// Update SelectedDates
this.Owner.SelectedDates.ClearInternal();
EndDrag(ctrl, selectedDate);
break;
}
case CalendarSelectionMode.MultipleRange:
{
// add the selection (either single day or SingleRange day)
EndDrag(ctrl, selectedDate);
break;
}
}
}
else
{
// If the day is blacked out but also a trailing day we should be able to switch months
CalendarDayButton b = GetCalendarDayButton(selectedDate);
if (b != null && b.IsInactive && b.IsBlackedOut)
{
this.Owner.OnDayClick(selectedDate);
}
}
}
private void Month_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
CalendarButton b = sender as CalendarButton;
if (b != null)
{
this._isMonthPressed = true;
Mouse.Capture(this, CaptureMode.SubTree);
if (this.Owner != null)
{
this.Owner.OnCalendarButtonPressed(b, false);
}
}
}
private void Month_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
CalendarButton b = sender as CalendarButton;
if (b != null && this.Owner != null)
{
this.Owner.OnCalendarButtonPressed(b, true);
}
}
private void Month_MouseEnter(object sender, MouseEventArgs e)
{
CalendarButton b = sender as CalendarButton;
if (b != null)
{
if (this._isMonthPressed && this.Owner != null)
{
this.Owner.OnCalendarButtonPressed(b, false);
}
}
}
private void Month_Clicked(object sender, RoutedEventArgs e)
{
CalendarButton b = sender as CalendarButton;
if (b != null)
{
this.Owner.OnCalendarButtonPressed(b, true);
}
}
private void HeaderButton_Click(object sender, RoutedEventArgs e)
{
if (this.Owner != null)
{
if (this.Owner.DisplayMode == CalendarMode.Month)
{
this.Owner.DisplayMode = CalendarMode.Year;
}
else
{
Debug.Assert(this.Owner.DisplayMode == CalendarMode.Year);
this.Owner.DisplayMode = CalendarMode.Decade;
}
this.FocusDate(this.DisplayDate);
}
}
private void PreviousButton_Click(object sender, RoutedEventArgs e)
{
if (this.Owner != null)
{
this.Owner.OnPreviousClick();
}
}
private void NextButton_Click(object sender, RoutedEventArgs e)
{
if (this.Owner != null)
{
this.Owner.OnNextClick();
}
}
private void PopulateGrids()
{
if (_monthView != null)
{
if (_dayTitleTemplate != null)
{
for (int i = 0; i < COLS; i++)
{
FrameworkElement titleCell = (FrameworkElement)this._dayTitleTemplate.LoadContent();
titleCell.SetValue(Grid.RowProperty, 0);
titleCell.SetValue(Grid.ColumnProperty, i);
this._monthView.Children.Add(titleCell);
}
}
for (int i = 1; i < ROWS; i++)
{
for (int j = 0; j < COLS; j++)
{
CalendarDayButton dayCell = new CalendarDayButton();
dayCell.Owner = this.Owner;
dayCell.SetValue(Grid.RowProperty, i);
dayCell.SetValue(Grid.ColumnProperty, j);
dayCell.SetBinding(CalendarDayButton.StyleProperty, GetOwnerBinding("CalendarDayButtonStyle"));
dayCell.AddHandler(CalendarDayButton.MouseLeftButtonDownEvent, new MouseButtonEventHandler(Cell_MouseLeftButtonDown), true);
dayCell.AddHandler(CalendarDayButton.MouseLeftButtonUpEvent, new MouseButtonEventHandler(Cell_MouseLeftButtonUp), true);
dayCell.AddHandler(CalendarDayButton.MouseEnterEvent, new MouseEventHandler(Cell_MouseEnter), true);
dayCell.Click += new RoutedEventHandler(Cell_Clicked);
dayCell.AddHandler(PreviewKeyDownEvent, new RoutedEventHandler(CellOrMonth_PreviewKeyDown), true);
this._monthView.Children.Add(dayCell);
}
}
}
if (_yearView != null)
{
CalendarButton monthCell;
int count = 0;
for (int i = 0; i < YEAR_ROWS; i++)
{
for (int j = 0; j < YEAR_COLS; j++)
{
monthCell = new CalendarButton();
monthCell.Owner = this.Owner;
monthCell.SetValue(Grid.RowProperty, i);
monthCell.SetValue(Grid.ColumnProperty, j);
monthCell.SetBinding(CalendarButton.StyleProperty, GetOwnerBinding("CalendarButtonStyle"));
monthCell.AddHandler(CalendarButton.MouseLeftButtonDownEvent, new MouseButtonEventHandler(Month_MouseLeftButtonDown), true);
monthCell.AddHandler(CalendarButton.MouseLeftButtonUpEvent, new MouseButtonEventHandler(Month_MouseLeftButtonUp), true);
monthCell.AddHandler(CalendarButton.MouseEnterEvent, new MouseEventHandler(Month_MouseEnter), true);
monthCell.AddHandler(UIElement.PreviewKeyDownEvent, new RoutedEventHandler(CellOrMonth_PreviewKeyDown), true);
monthCell.Click += new RoutedEventHandler(Month_Clicked);
this._yearView.Children.Add(monthCell);
count++;
}
}
}
}
#region Month Mode Display
private void SetMonthModeDayTitles()
{
if (_monthView != null)
{
string[] shortestDayNames = DateTimeHelper.GetDateFormat(DateTimeHelper.GetCulture(this)).ShortestDayNames;
for (int childIndex = 0; childIndex < COLS; childIndex++)
{
FrameworkElement daytitle = _monthView.Children[childIndex] as FrameworkElement;
if (daytitle != null && shortestDayNames != null && shortestDayNames.Length > 0)
{
if (this.Owner != null)
{
daytitle.DataContext = shortestDayNames[(childIndex + (int)this.Owner.FirstDayOfWeek) % shortestDayNames.Length];
}
else
{
daytitle.DataContext = shortestDayNames[(childIndex + (int)DateTimeHelper.GetDateFormat(DateTimeHelper.GetCulture(this)).FirstDayOfWeek) % shortestDayNames.Length];
}
}
}
}
}
private void SetMonthModeCalendarDayButtons()
{
DateTime firstDayOfMonth = DateTimeHelper.DiscardDayTime(DisplayDate);
int lastMonthToDisplay = GetNumberOfDisplayedDaysFromPreviousMonth(firstDayOfMonth);
bool isMinMonth = DateTimeHelper.CompareYearMonth(firstDayOfMonth, DateTime.MinValue) <= 0;
bool isMaxMonth = DateTimeHelper.CompareYearMonth(firstDayOfMonth, DateTime.MaxValue) >= 0;
int daysInMonth = _calendar.GetDaysInMonth(firstDayOfMonth.Year, firstDayOfMonth.Month);
CultureInfo culture = DateTimeHelper.GetCulture(this);
int count = ROWS * COLS;
for (int childIndex = COLS; childIndex < count; childIndex++)
{
CalendarDayButton childButton = _monthView.Children[childIndex] as CalendarDayButton;
Debug.Assert(childButton != null);
int dayOffset = childIndex - lastMonthToDisplay - COLS;
if ((!isMinMonth || (dayOffset >= 0)) && (!isMaxMonth || (dayOffset < daysInMonth)))
{
DateTime dateToAdd = _calendar.AddDays(firstDayOfMonth, dayOffset);
SetMonthModeDayButtonState(childButton, dateToAdd);
childButton.DataContext = dateToAdd;
childButton.SetContentInternal(DateTimeHelper.ToDayString(dateToAdd, culture));
}
else
{
SetMonthModeDayButtonState(childButton, null);
childButton.DataContext = null;
childButton.SetContentInternal(DateTimeHelper.ToDayString(null, culture));
}
}
}
private void SetMonthModeDayButtonState(CalendarDayButton childButton, DateTime? dateToAdd)
{
if (this.Owner != null)
{
if (dateToAdd.HasValue)
{
childButton.Visibility = Visibility.Visible;
// If the day is outside the DisplayDateStart/End boundary, do not show it
if (DateTimeHelper.CompareDays(dateToAdd.Value, this.Owner.DisplayDateStartInternal) < 0 || DateTimeHelper.CompareDays(dateToAdd.Value, this.Owner.DisplayDateEndInternal) > 0)
{
childButton.IsEnabled = false;
childButton.Visibility = Visibility.Hidden;
}
else
{
childButton.IsEnabled = true;
// SET IF THE DAY IS SELECTABLE OR NOT
childButton.SetValue(
CalendarDayButton.IsBlackedOutPropertyKey,
this.Owner.BlackoutDates.Contains(dateToAdd.Value));
// SET IF THE DAY IS ACTIVE OR NOT: set if the day is a trailing day or not
childButton.SetValue(
CalendarDayButton.IsInactivePropertyKey,
DateTimeHelper.CompareYearMonth(dateToAdd.Value, this.Owner.DisplayDateInternal) != 0);
// SET IF THE DAY IS TODAY OR NOT
if (DateTimeHelper.CompareDays(dateToAdd.Value, DateTime.Today) == 0)
{
childButton.SetValue(CalendarDayButton.IsTodayPropertyKey, true);
// Calendar.IsTodayHighlighted affects the final visual state for Today buttons
// but childButton property change callbacks are no called in response to
// Calendar.IsTodayHighlighted changing so we must explicitly update the visual state
childButton.ChangeVisualState(true);
}
else
{
childButton.SetValue(CalendarDayButton.IsTodayPropertyKey, false);
}
// SET IF THE DAY IS SELECTED OR NOT
// Since we should be comparing the Date values not DateTime values, we can't use this.Owner.SelectedDates.Contains(dateToAdd) directly
bool isSelected = false;
foreach (DateTime item in this.Owner.SelectedDates)
{
isSelected |= (DateTimeHelper.CompareDays(dateToAdd.Value, item) == 0);
}
childButton.SetValue(CalendarDayButton.IsSelectedPropertyKey, isSelected);
}
}
else
{
childButton.Visibility = Visibility.Hidden;
childButton.IsEnabled = false;
childButton.SetValue(CalendarDayButton.IsBlackedOutPropertyKey, false);
childButton.SetValue(CalendarDayButton.IsInactivePropertyKey, true);
childButton.SetValue(CalendarDayButton.IsTodayPropertyKey, false);
childButton.SetValue(CalendarDayButton.IsSelectedPropertyKey, false);
}
}
}
private void AddMonthModeHighlight()
{
var owner = this.Owner;
if (owner == null)
{
return;
}
if (owner.HoverStart.HasValue && owner.HoverEnd.HasValue)
{
DateTime hStart = owner.HoverEnd.Value;
DateTime hEnd = owner.HoverEnd.Value;
int daysToHighlight = DateTimeHelper.CompareDays(owner.HoverEnd.Value, owner.HoverStart.Value);
if (daysToHighlight < 0)
{
hEnd = this.Owner.HoverStart.Value;
}
else
{
hStart = this.Owner.HoverStart.Value;
}
int count = ROWS * COLS;
for (int childIndex = COLS; childIndex < count; childIndex++)
{
CalendarDayButton childButton = _monthView.Children[childIndex] as CalendarDayButton;
if (childButton.DataContext is DateTime)
{
DateTime date = (DateTime)childButton.DataContext;
childButton.SetValue(
CalendarDayButton.IsHighlightedPropertyKey,
(daysToHighlight != 0) && DateTimeHelper.InRange(date, hStart, hEnd));
}
else
{
childButton.SetValue(CalendarDayButton.IsHighlightedPropertyKey, false);
}
}
}
else
{
int count = ROWS * COLS;
for (int childIndex = COLS; childIndex < count; childIndex++)
{
CalendarDayButton childButton = _monthView.Children[childIndex] as CalendarDayButton;
childButton.SetValue(CalendarDayButton.IsHighlightedPropertyKey, false);
}
}
}
private void SetMonthModeHeaderButton()
{
if (this._headerButton != null)
{
this._headerButton.Content = DateTimeHelper.ToYearMonthPatternString(DisplayDate, DateTimeHelper.GetCulture(this));
if (this.Owner != null)
{
this._headerButton.IsEnabled = true;
}
}
}
private void SetMonthModeNextButton()
{
if (this.Owner != null && _nextButton != null)
{
DateTime firstDayOfMonth = DateTimeHelper.DiscardDayTime(DisplayDate);
// DisplayDate is equal to DateTime.MaxValue
if (DateTimeHelper.CompareYearMonth(firstDayOfMonth, DateTime.MaxValue) == 0)
{
_nextButton.IsEnabled = false;
}
else
{
// Since we are sure DisplayDate is not equal to DateTime.MaxValue,
// it is safe to use AddMonths
DateTime firstDayOfNextMonth = _calendar.AddMonths(firstDayOfMonth, 1);
_nextButton.IsEnabled = (DateTimeHelper.CompareDays(this.Owner.DisplayDateEndInternal, firstDayOfNextMonth) > -1);
}
}
}
private void SetMonthModePreviousButton()
{
if (this.Owner != null && _previousButton != null)
{
DateTime firstDayOfMonth = DateTimeHelper.DiscardDayTime(DisplayDate);
_previousButton.IsEnabled = (DateTimeHelper.CompareDays(this.Owner.DisplayDateStartInternal, firstDayOfMonth) < 0);
}
}
#endregion
#region Year Mode Display
private void SetYearButtons(int decade, int decadeEnd)
{
int year;
int count = -1;
foreach (object child in _yearView.Children)
{
CalendarButton childButton = child as CalendarButton;
Debug.Assert(childButton != null);
year = decade + count;
if (year <= DateTime.MaxValue.Year && year >= DateTime.MinValue.Year)
{
// There should be no time component. Time is 12:00 AM
DateTime day = new DateTime(year, 1, 1);
childButton.DataContext = day;
childButton.SetContentInternal(DateTimeHelper.ToYearString(day, DateTimeHelper.GetCulture(this)));
childButton.Visibility = Visibility.Visible;
if (this.Owner != null)
{
childButton.HasSelectedDays = (Owner.DisplayDate.Year == year);
if (year < this.Owner.DisplayDateStartInternal.Year || year > this.Owner.DisplayDateEndInternal.Year)
{
childButton.IsEnabled = false;
childButton.Opacity = 0;
}
else
{
childButton.IsEnabled = true;
childButton.Opacity = 1;
}
}
// SET IF THE YEAR IS INACTIVE OR NOT: set if the year is a trailing year or not
childButton.IsInactive = year < decade || year > decadeEnd;
}
else
{
childButton.DataContext = null;
childButton.IsEnabled = false;
childButton.Opacity = 0;
}
count++;
}
}
private void SetYearModeMonthButtons()
{
int count = 0;
foreach (object child in _yearView.Children)
{
CalendarButton childButton = child as CalendarButton;
Debug.Assert(childButton != null);
// There should be no time component. Time is 12:00 AM
DateTime day = new DateTime(DisplayDate.Year, count + 1, 1);
childButton.DataContext = day;
childButton.SetContentInternal(DateTimeHelper.ToAbbreviatedMonthString(day,DateTimeHelper.GetCulture(this)));
childButton.Visibility = Visibility.Visible;
if (this.Owner != null)
{
Debug.Assert(this.Owner.DisplayDateInternal != null);
childButton.HasSelectedDays = (DateTimeHelper.CompareYearMonth(day, this.Owner.DisplayDateInternal) == 0);
if (DateTimeHelper.CompareYearMonth(day, this.Owner.DisplayDateStartInternal) < 0 || DateTimeHelper.CompareYearMonth(day, this.Owner.DisplayDateEndInternal) > 0)
{
childButton.IsEnabled = false;
childButton.Opacity = 0;
}
else
{
childButton.IsEnabled = true;
childButton.Opacity = 1;
}
}
childButton.IsInactive = false;
count++;
}
}
private void SetYearModeHeaderButton()
{
if (this._headerButton != null)
{
this._headerButton.IsEnabled = true;
this._headerButton.Content = DateTimeHelper.ToYearString(DisplayDate, DateTimeHelper.GetCulture(this));
}
}
private void SetYearModeNextButton()
{
if (this.Owner != null && _nextButton != null)
{
_nextButton.IsEnabled = (this.Owner.DisplayDateEndInternal.Year != DisplayDate.Year);
}
}
private void SetYearModePreviousButton()
{
if (this.Owner != null && _previousButton != null)
{
_previousButton.IsEnabled = (this.Owner.DisplayDateStartInternal.Year != DisplayDate.Year);
}
}
#endregion Year Mode Display
#region Decade Mode Display
private void SetDecadeModeHeaderButton(int decade)
{
if (this._headerButton != null)
{
this._headerButton.Content = DateTimeHelper.ToDecadeRangeString(decade, DateTimeHelper.GetCulture(this));
this._headerButton.IsEnabled = false;
}
}
private void SetDecadeModeNextButton(int decadeEnd)
{
if (this.Owner != null && _nextButton != null)
{
_nextButton.IsEnabled = (this.Owner.DisplayDateEndInternal.Year > decadeEnd);
}
}
private void SetDecadeModePreviousButton(int decade)
{
if (this.Owner != null && _previousButton != null)
{
_previousButton.IsEnabled = (decade > this.Owner.DisplayDateStartInternal.Year);
}
}
#endregion Decade Mode Display
// How many days of the previous month need to be displayed
private int GetNumberOfDisplayedDaysFromPreviousMonth(DateTime firstOfMonth)
{
DayOfWeek day = _calendar.GetDayOfWeek(firstOfMonth);
int i;
if (this.Owner != null)
{
i = ((day - this.Owner.FirstDayOfWeek + NUMBER_OF_DAYS_IN_WEEK) % NUMBER_OF_DAYS_IN_WEEK);
}
else
{
i = ((day - DateTimeHelper.GetDateFormat(DateTimeHelper.GetCulture(this)).FirstDayOfWeek + NUMBER_OF_DAYS_IN_WEEK) % NUMBER_OF_DAYS_IN_WEEK);
}
if (i == 0)
{
return NUMBER_OF_DAYS_IN_WEEK;
}
else
{
return i;
}
}
///
/// Gets a binding to a property on the owning calendar
///
///
///
private BindingBase GetOwnerBinding(string propertyName)
{
Binding result = new Binding(propertyName);
result.Source = this.Owner;
return result;
}
#endregion Private Methods
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Controls/CalendarMode.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
namespace Microsoft.Windows.Controls
{
///
/// Specifies values for the different modes of operation of a Calendar.
///
public enum CalendarMode
{
///
/// The Calendar displays a month at a time.
///
Month = 0,
///
/// The Calendar displays a year at a time.
///
Year = 1,
///
/// The Calendar displays a decade at a time.
///
Decade = 2,
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Controls/CalendarModeChangedEventArgs.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
namespace Microsoft.Windows.Controls
{
///
/// Provides data for the DisplayModeChanged event.
///
public class CalendarModeChangedEventArgs : System.Windows.RoutedEventArgs
{
///
/// Initializes a new instance of the CalendarModeChangedEventArgs class.
///
/// Previous value of the property, prior to the event being raised.
/// Current value of the property at the time of the event.
public CalendarModeChangedEventArgs(CalendarMode oldMode, CalendarMode newMode)
{
this.OldMode = oldMode;
this.NewMode = newMode;
}
///
/// Gets the new mode of the Calendar.
///
public CalendarMode NewMode
{
get;
private set;
}
///
/// Gets the previous mode of the Calendar.
///
public CalendarMode OldMode
{
get;
private set;
}
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Controls/CalendarSelectionChangedEventArgs.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
namespace Microsoft.Windows.Controls
{
///
/// Workaround for Dev10 Bug 527138 UIElement.RaiseEvent(e) throws InvalidCastException when
/// e is of type SelectionChangedEventArgs
/// e.RoutedEvent was registered with a handler not of type System.Windows.Controls.SelectionChangedEventHandler
///
internal class CalendarSelectionChangedEventArgs : SelectionChangedEventArgs
{
///
/// Constructor
///
/// Routed Event
/// Items removed from selection
/// Items added to selection
public CalendarSelectionChangedEventArgs(RoutedEvent eventId, IList removedItems, IList addedItems) :
base(eventId, removedItems, addedItems)
{
}
protected override void InvokeEventHandler(Delegate genericHandler, object genericTarget)
{
EventHandler handler = genericHandler as EventHandler;
if (handler != null)
{
handler(genericTarget, this);
}
else
{
base.InvokeEventHandler(genericHandler, genericTarget);
}
}
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Controls/CalendarSelectionMode.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
namespace Microsoft.Windows.Controls
{
///
/// Specifies values for the different selection modes of a Calendar.
///
public enum CalendarSelectionMode
{
///
/// One date can be selected at a time.
///
SingleDate = 0,
///
/// One range of dates can be selected at a time.
///
SingleRange = 1,
///
/// Multiple dates or ranges can be selected at a time.
///
MultipleRange = 2,
///
/// No dates can be selected.
///
None = 3,
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Controls/DateTimeHelper.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to [###LICENSE_NAME###].
// Please see [###LICENSE_LINK###] for details.
// All other rights reserved.
using System;
using System.Diagnostics;
using System.Globalization;
using System.Windows;
using System.Windows.Markup;
namespace Microsoft.Windows.Controls
{
// NOTICE: This date time helper assumes it is working in a Gregorian calendar
// If we ever support non Gregorian calendars this class would need to be redesigned
internal static class DateTimeHelper
{
private static System.Globalization.Calendar cal = new GregorianCalendar();
public static DateTime? AddDays(DateTime time, int days)
{
try
{
return cal.AddDays(time, days);
}
catch (System.ArgumentException)
{
return null;
}
}
public static DateTime? AddMonths(DateTime time, int months)
{
try
{
return cal.AddMonths(time, months);
}
catch (System.ArgumentException)
{
return null;
}
}
public static DateTime? AddYears(DateTime time, int years)
{
try
{
return cal.AddYears(time, years);
}
catch (System.ArgumentException)
{
return null;
}
}
public static DateTime? SetYear(DateTime date, int year)
{
return DateTimeHelper.AddYears(date, year - date.Year);
}
public static DateTime? SetYearMonth(DateTime date, DateTime yearMonth)
{
DateTime? target = SetYear(date, yearMonth.Year);
if (target.HasValue)
{
target = DateTimeHelper.AddMonths(target.Value, yearMonth.Month - date.Month);
}
return target;
}
public static int CompareDays(DateTime dt1, DateTime dt2)
{
return DateTime.Compare(DiscardTime(dt1).Value, DiscardTime(dt2).Value);
}
public static int CompareYearMonth(DateTime dt1, DateTime dt2)
{
return ((dt1.Year - dt2.Year) * 12) + (dt1.Month - dt2.Month);
}
public static int DecadeOfDate(DateTime date)
{
return date.Year - (date.Year % 10);
}
public static DateTime DiscardDayTime(DateTime d)
{
return new DateTime(d.Year, d.Month, 1, 0, 0, 0);
}
public static DateTime? DiscardTime(DateTime? d)
{
if (d == null)
{
return null;
}
return d.Value.Date;
}
public static int EndOfDecade(DateTime date)
{
return DecadeOfDate(date) + 9;
}
public static DateTimeFormatInfo GetCurrentDateFormat()
{
return GetDateFormat(CultureInfo.CurrentCulture);
}
internal static CultureInfo GetCulture(FrameworkElement element)
{
CultureInfo culture;
if (DependencyPropertyHelper.GetValueSource(element, FrameworkElement.LanguageProperty).BaseValueSource != BaseValueSource.Default)
{
culture = GetCultureInfo(element);
}
else
{
culture = CultureInfo.CurrentCulture;
}
return culture;
}
// ------------------------------------------------------------------
// Retrieve CultureInfo property from specified element.
// ------------------------------------------------------------------
internal static CultureInfo GetCultureInfo(DependencyObject element)
{
XmlLanguage language = (XmlLanguage)element.GetValue(FrameworkElement.LanguageProperty);
try
{
return language.GetSpecificCulture();
}
catch (InvalidOperationException)
{
// We default to en-US if no part of the language tag is recognized.
return CultureInfo.ReadOnly(new CultureInfo("en-us", false));
}
}
internal static DateTimeFormatInfo GetDateFormat(CultureInfo culture)
{
if (culture.Calendar is GregorianCalendar)
{
return culture.DateTimeFormat;
}
else
{
GregorianCalendar foundCal = null;
DateTimeFormatInfo dtfi = null;
foreach (System.Globalization.Calendar cal in culture.OptionalCalendars)
{
if (cal is GregorianCalendar)
{
// Return the first Gregorian calendar with CalendarType == Localized
// Otherwise return the first Gregorian calendar
if (foundCal == null)
{
foundCal = cal as GregorianCalendar;
}
if (((GregorianCalendar)cal).CalendarType == GregorianCalendarTypes.Localized)
{
foundCal = cal as GregorianCalendar;
break;
}
}
}
if (foundCal == null)
{
// if there are no GregorianCalendars in the OptionalCalendars list, use the invariant dtfi
dtfi = ((CultureInfo)CultureInfo.InvariantCulture.Clone()).DateTimeFormat;
dtfi.Calendar = new GregorianCalendar();
}
else
{
dtfi = ((CultureInfo)culture.Clone()).DateTimeFormat;
dtfi.Calendar = foundCal;
}
return dtfi;
}
}
// returns if the date is included in the range
public static bool InRange(DateTime date, CalendarDateRange range)
{
return InRange(date, range.Start, range.End);
}
// returns if the date is included in the range
public static bool InRange(DateTime date, DateTime start, DateTime end)
{
Debug.Assert(DateTime.Compare(start, end) < 1);
if (CompareDays(date, start) > -1 && CompareDays(date, end) < 1)
{
return true;
}
return false;
}
public static string ToDayString(DateTime? date, CultureInfo culture)
{
string result = string.Empty;
DateTimeFormatInfo format = GetDateFormat(culture);
if (date.HasValue && format != null)
{
result = date.Value.Day.ToString(format);
}
return result;
}
public static string ToDecadeRangeString(int decade, CultureInfo culture)
{
string result = string.Empty;
DateTimeFormatInfo format = culture.DateTimeFormat;
if (format != null)
{
int decadeEnd = decade + 9;
result = decade.ToString(format) + "-" + decadeEnd.ToString(format);
}
return result;
}
public static string ToYearMonthPatternString(DateTime? date, CultureInfo culture)
{
string result = string.Empty;
DateTimeFormatInfo format = GetDateFormat(culture);
if (date.HasValue && format != null)
{
result = date.Value.ToString(format.YearMonthPattern, format);
}
return result;
}
public static string ToYearString(DateTime? date, CultureInfo culture)
{
string result = string.Empty;
DateTimeFormatInfo format = GetDateFormat(culture);
if (date.HasValue && format != null)
{
result = date.Value.Year.ToString(format);
}
return result;
}
public static string ToAbbreviatedMonthString(DateTime? date, CultureInfo culture)
{
string result = string.Empty;
DateTimeFormatInfo format = GetDateFormat(culture);
if (date.HasValue && format != null)
{
string[] monthNames = format.AbbreviatedMonthNames;
if (monthNames != null && monthNames.Length > 0)
{
result = monthNames[(date.Value.Month - 1) % monthNames.Length];
}
}
return result;
}
public static string ToLongDateString(DateTime? date, CultureInfo culture)
{
string result = string.Empty;
DateTimeFormatInfo format = GetDateFormat(culture);
if (date.HasValue && format != null)
{
result = date.Value.Date.ToString(format.LongDatePattern, format);
}
return result;
}
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Controls/KeyboardHelper.cs
================================================
using System.Windows.Input;
namespace Microsoft.Windows.Controls
{
internal static class KeyboardHelper
{
public static void GetMetaKeyState(out bool ctrl, out bool shift)
{
ctrl = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control;
shift = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;
}
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Controls/SelectedDatesCollection.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
namespace Microsoft.Windows.Controls
{
///
/// Represents the collection of SelectedDates for the Calendar Control.
///
public sealed class SelectedDatesCollection : ObservableCollection
{
#region Data
private Collection _addedItems;
private Collection _removedItems;
private Thread _dispatcherThread;
private bool _isAddingRange;
private Calendar _owner;
private DateTime? _maximumDate;
private DateTime? _minimumDate;
#endregion Data
///
/// Initializes a new instance of the CalendarSelectedDatesCollection class.
///
///
public SelectedDatesCollection(Calendar owner)
{
this._dispatcherThread = Thread.CurrentThread;
this._owner = owner;
this._addedItems = new Collection();
this._removedItems = new Collection();
}
#region Internal Properties
internal DateTime? MinimumDate
{
get
{
if (Count < 1)
{
return null;
}
if (!_minimumDate.HasValue)
{
DateTime result = this[0];
foreach (DateTime selectedDate in this)
{
if (DateTime.Compare(selectedDate, result) < 0)
{
result = selectedDate;
}
}
_maximumDate = result;
}
return _minimumDate;
}
}
internal DateTime? MaximumDate
{
get
{
if (Count < 1)
{
return null;
}
if (!_maximumDate.HasValue)
{
DateTime result = this[0];
foreach (DateTime selectedDate in this)
{
if (DateTime.Compare(selectedDate, result) > 0)
{
result = selectedDate;
}
}
_maximumDate = result;
}
return _maximumDate;
}
}
#endregion
#region Public methods
///
/// Adds a range of dates to the Calendar SelectedDates.
///
///
///
public void AddRange(DateTime start, DateTime end)
{
BeginAddRange();
// If CalendarSelectionMode.SingleRange and a user programmatically tries to add multiple ranges, we will throw away the old range and replace it with the new one.
if (this._owner.SelectionMode == CalendarSelectionMode.SingleRange && this.Count > 0)
{
this.ClearInternal();
}
foreach (DateTime current in GetDaysInRange(start, end))
{
this.Add(current);
}
EndAddRange();
}
#endregion Public Methods
#region Protected methods
///
/// Clears all the items of the SelectedDates.
///
protected override void ClearItems()
{
if (!IsValidThread())
{
throw new NotSupportedException(SR.Get(SRID.CalendarCollection_MultiThreadedCollectionChangeNotSupported));
}
// Turn off highlight
this._owner.HoverStart = null;
ClearInternal(true /*fireChangeNotification*/);
}
///
/// Inserts the item in the specified position of the SelectedDates collection.
///
///
///
protected override void InsertItem(int index, DateTime item)
{
if (!IsValidThread())
{
throw new NotSupportedException(SR.Get(SRID.CalendarCollection_MultiThreadedCollectionChangeNotSupported));
}
if (!this.Contains(item))
{
Collection addedItems = new Collection();
bool isCleared = CheckSelectionMode();
if (Calendar.IsValidDateSelection(this._owner, item))
{
// If the Collection is cleared since it is SingleRange and it had another range
// set the index to 0
if (isCleared)
{
index = 0;
isCleared = false;
}
base.InsertItem(index, item);
UpdateMinMax(item);
// The event fires after SelectedDate changes
if (index == 0 && !(this._owner.SelectedDate.HasValue && DateTime.Compare(this._owner.SelectedDate.Value, item) == 0))
{
this._owner.SelectedDate = item;
}
if (!_isAddingRange)
{
addedItems.Add(item);
RaiseSelectionChanged(this._removedItems, addedItems);
this._removedItems.Clear();
int monthDifference = DateTimeHelper.CompareYearMonth(item, this._owner.DisplayDateInternal);
if (monthDifference < 2 && monthDifference > -2)
{
this._owner.UpdateCellItems();
}
}
else
{
this._addedItems.Add(item);
}
}
else
{
throw new ArgumentOutOfRangeException(SR.Get(SRID.Calendar_OnSelectedDateChanged_InvalidValue));
}
}
}
///
/// Removes the item at the specified position.
///
///
protected override void RemoveItem(int index)
{
if (!IsValidThread())
{
throw new NotSupportedException(SR.Get(SRID.CalendarCollection_MultiThreadedCollectionChangeNotSupported));
}
if (index >= this.Count)
{
base.RemoveItem(index);
ClearMinMax();
}
else
{
Collection addedItems = new Collection();
Collection removedItems = new Collection();
int monthDifference = DateTimeHelper.CompareYearMonth(this[index], this._owner.DisplayDateInternal);
removedItems.Add(this[index]);
base.RemoveItem(index);
ClearMinMax();
// The event fires after SelectedDate changes
if (index == 0)
{
if (Count > 0)
{
this._owner.SelectedDate = this[0];
}
else
{
this._owner.SelectedDate = null;
}
}
RaiseSelectionChanged(removedItems, addedItems);
if (monthDifference < 2 && monthDifference > -2)
{
this._owner.UpdateCellItems();
}
}
}
///
/// The object in the specified index is replaced with the provided item.
///
///
///
protected override void SetItem(int index, DateTime item)
{
if (!IsValidThread())
{
throw new NotSupportedException(SR.Get(SRID.CalendarCollection_MultiThreadedCollectionChangeNotSupported));
}
if (!this.Contains(item))
{
Collection addedItems = new Collection();
Collection removedItems = new Collection();
if (index >= this.Count)
{
base.SetItem(index, item);
UpdateMinMax(item);
}
else
{
if (item != null && DateTime.Compare(this[index], item) != 0 && Calendar.IsValidDateSelection(this._owner, item))
{
removedItems.Add(this[index]);
base.SetItem(index, item);
UpdateMinMax(item);
addedItems.Add(item);
// The event fires after SelectedDate changes
if (index == 0 && !(this._owner.SelectedDate.HasValue && DateTime.Compare(this._owner.SelectedDate.Value, item) == 0))
{
this._owner.SelectedDate = item;
}
RaiseSelectionChanged(removedItems, addedItems);
int monthDifference = DateTimeHelper.CompareYearMonth(item, this._owner.DisplayDateInternal);
if (monthDifference < 2 && monthDifference > -2)
{
this._owner.UpdateCellItems();
}
}
}
}
}
#endregion Protected methods
#region Internal Methods
///
/// Adds a range of dates to the Calendar SelectedDates.
///
///
/// Helper version of AddRange for mouse drag selection.
/// This version guarantees no exceptions will be thrown by removing blackout days from the range before adding to the collection
///
internal void AddRangeInternal(DateTime start, DateTime end)
{
BeginAddRange();
// In Mouse Selection we allow the user to be able to add multiple ranges in one action in MultipleRange Mode
// In SingleRange Mode, we only add the first selected range
DateTime lastAddedDate = start;
foreach (DateTime current in GetDaysInRange(start, end))
{
if (Calendar.IsValidDateSelection(this._owner, current))
{
this.Add(current);
lastAddedDate = current;
}
else
{
if (this._owner.SelectionMode == CalendarSelectionMode.SingleRange)
{
this._owner.CurrentDate = lastAddedDate;
break;
}
}
}
EndAddRange();
}
internal void ClearInternal()
{
ClearInternal(false /*fireChangeNotification*/);
}
internal void ClearInternal(bool fireChangeNotification)
{
if (this.Count > 0)
{
foreach (DateTime item in this)
{
_removedItems.Add(item);
}
base.ClearItems();
ClearMinMax();
if (fireChangeNotification)
{
if (this._owner.SelectedDate != null)
{
this._owner.SelectedDate = null;
}
if (_removedItems.Count > 0)
{
Collection addedItems = new Collection();
RaiseSelectionChanged(_removedItems, addedItems);
_removedItems.Clear();
}
this._owner.UpdateCellItems();
}
}
}
internal void Toggle(DateTime date)
{
if (Calendar.IsValidDateSelection(this._owner, date))
{
switch (this._owner.SelectionMode)
{
case CalendarSelectionMode.SingleDate:
{
if (!this._owner.SelectedDate.HasValue || DateTimeHelper.CompareDays(this._owner.SelectedDate.Value, date) != 0)
{
this._owner.SelectedDate = date;
}
else
{
this._owner.SelectedDate = null;
}
break;
}
case CalendarSelectionMode.MultipleRange:
{
if (!Remove(date))
{
Add(date);
}
break;
}
default:
{
Debug.Assert(false);
break;
}
}
}
}
#endregion Internal Methods
#region Private Methods
private void RaiseSelectionChanged(IList removedItems, IList addedItems)
{
this._owner.OnSelectedDatesCollectionChanged(new CalendarSelectionChangedEventArgs(Calendar.SelectedDatesChangedEvent, removedItems, addedItems));
}
private void BeginAddRange()
{
Debug.Assert(!_isAddingRange);
_isAddingRange = true;
}
private void EndAddRange()
{
Debug.Assert(_isAddingRange);
_isAddingRange = false;
RaiseSelectionChanged(this._removedItems, this._addedItems);
this._removedItems.Clear();
this._addedItems.Clear();
this._owner.UpdateCellItems();
}
private bool CheckSelectionMode()
{
if (this._owner.SelectionMode == CalendarSelectionMode.None)
{
throw new InvalidOperationException(SR.Get(SRID.Calendar_OnSelectedDateChanged_InvalidOperation));
}
if (this._owner.SelectionMode == CalendarSelectionMode.SingleDate && this.Count > 0)
{
throw new InvalidOperationException(SR.Get(SRID.Calendar_CheckSelectionMode_InvalidOperation));
}
// if user tries to add an item into the SelectedDates in SingleRange mode, we throw away the old range and replace it with the new one
// in order to provide the removed items without an additional event, we are calling ClearInternal
if (this._owner.SelectionMode == CalendarSelectionMode.SingleRange && !_isAddingRange && this.Count > 0)
{
this.ClearInternal();
return true;
}
else
{
return false;
}
}
private bool IsValidThread()
{
return Thread.CurrentThread == this._dispatcherThread;
}
private void UpdateMinMax(DateTime date)
{
if ((!_maximumDate.HasValue) || (date > _maximumDate.Value))
{
_maximumDate = date;
}
if ((!_minimumDate.HasValue) || (date < _minimumDate.Value))
{
_minimumDate = date;
}
}
private void ClearMinMax()
{
_maximumDate = null;
_minimumDate = null;
}
private static IEnumerable GetDaysInRange(DateTime start, DateTime end)
{
// increment parameter specifies if the Days were selected in Descending order or Ascending order
// based on this value, we add the days in the range either in Ascending order or in Descending order
int increment = GetDirection(start, end);
DateTime? rangeStart = start;
do
{
yield return rangeStart.Value;
rangeStart = DateTimeHelper.AddDays(rangeStart.Value, increment);
}
while (rangeStart.HasValue && DateTime.Compare(end, rangeStart.Value) != -increment);
}
private static int GetDirection(DateTime start, DateTime end)
{
return (DateTime.Compare(end, start) >= 0) ? 1 : -1;
}
#endregion Private Methods
}
}
================================================
FILE: WpfToolkit/Calendar/Microsoft/Windows/Controls/VisualStates.cs
================================================
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.Windows;
using System.Windows.Controls;
namespace Microsoft.Windows.Controls
{
///
/// Names and helpers for visual states in the controls.
///
internal static class VisualStates
{
#region GroupCalendarButtonFocus
///
/// Unfocused state for Calendar Buttons
///
public const string StateCalendarButtonUnfocused = "CalendarButtonUnfocused";
///
/// Focused state for Calendar Buttons
///
public const string StateCalendarButtonFocused = "CalendarButtonFocused";
///
/// CalendarButtons Focus state group
///
public const string GroupCalendarButtonFocus = "CalendarButtonFocusStates";
#endregion GroupCalendarButtonFocus
#region GroupCommon
///
/// Normal state
///
public const string StateNormal = "Normal";
///
/// MouseOver state
///
public const string StateMouseOver = "MouseOver";
///
/// Pressed state
///
public const string StatePressed = "Pressed";
///
/// Disabled state
///
public const string StateDisabled = "Disabled";
///
/// Common state group
///
public const string GroupCommon = "CommonStates";
#endregion GroupCommon
#region GroupFocus
///
/// Unfocused state
///
public const string StateUnfocused = "Unfocused";
///
/// Focused state
///
public const string StateFocused = "Focused";
///
/// Focus state group
///
public const string GroupFocus = "FocusStates";
#endregion GroupFocus
#region GroupSelection
///
/// Selected state
///
public const string StateSelected = "Selected";
///
/// Unselected state
///
public const string StateUnselected = "Unselected";
///
/// Selection state group
///
public const string GroupSelection = "SelectionStates";
#endregion GroupSelection
#region GroupActive
///
/// Active state
///
public const string StateActive = "Active";
///
/// Inactive state
///
public const string StateInactive = "Inactive";
///
/// Active state group
///
public const string GroupActive = "ActiveStates";
#endregion GroupActive
#region GroupValidation
///
/// Valid state
///
public const string StateValid = "Valid";
///
/// InvalidFocused state
///
public const string StateInvalidFocused = "InvalidFocused";
///
/// InvalidUnfocused state
///
public const string StateInvalidUnfocused = "InvalidUnfocused";
///
/// Validation state group
///
public const string GroupValidation = "ValidationStates";
#endregion GroupValidation
#region GroupWatermark
///
/// Unwatermarked state
///
public const string StateUnwatermarked = "Unwatermarked";
///
/// Watermarked state
///
public const string StateWatermarked = "Watermarked";
///
/// Watermark state group
///
public const string GroupWatermark = "WatermarkStates";
#endregion GroupWatermark
///
/// Use VisualStateManager to change the visual state of the control.
///
///
/// Control whose visual state is being changed.
///
///
/// true to use transitions when updating the visual state, false to
/// snap directly to the new visual state.
///
///
/// Ordered list of state names and fallback states to transition into.
/// Only the first state to be found will be used.
///
public static void GoToState(Control control, bool useTransitions, params string[] stateNames)
{
if (control == null)
{
throw new ArgumentNullException("control");
}
if (stateNames == null)
{
return;
}
foreach (string name in stateNames)
{
if (VisualStateManager.GoToState(control, name, useTransitions))
{
break;
}
}
}
}
}
================================================
FILE: WpfToolkit/Calendar/Themes/Aero.NormalColor.xaml
================================================
Aero.NormalColor
================================================
FILE: WpfToolkit/Calendar/Themes/Classic.xaml
================================================
Classic
================================================
FILE: WpfToolkit/Calendar/Themes/Generic.xaml
================================================
================================================
FILE: WpfToolkit/Calendar/Themes/Luna.HomeStead.xaml
================================================
Luna.HomeStead
================================================
FILE: WpfToolkit/Calendar/Themes/Luna.Metallic.xaml
================================================
Luna.Metallic
================================================
FILE: WpfToolkit/Calendar/Themes/Luna.NormalColor.xaml
================================================
Luna.NormalColor
================================================
FILE: WpfToolkit/Calendar/Themes/Royale.NormalColor.xaml
================================================
Royale.NormalColor
================================================
FILE: WpfToolkit/Common/System/Windows/Controls/BindingEvaluator.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993] for details.
// All other rights reserved.
using System.Windows.Data;
namespace System.Windows.Controls
{
///
/// A framework element that permits a binding to be evaluated in a new data
/// context leaf node.
///
/// The type of dynamic binding to return.
internal partial class BindingEvaluator : FrameworkElement
{
///
/// Gets or sets the string value binding used by the control.
///
private Binding _binding;
#region public T Value
///
/// Gets or sets the data item string value.
///
public T Value
{
get { return (T)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
///
/// Identifies the Value dependency property.
///
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(
"Value",
typeof(T),
typeof(BindingEvaluator),
new PropertyMetadata(default(T)));
#endregion public string Value
///
/// Gets or sets the value binding.
///
public Binding ValueBinding
{
get { return _binding; }
set
{
_binding = value;
SetBinding(ValueProperty, _binding);
}
}
///
/// Initializes a new instance of the BindingEvaluator class.
///
public BindingEvaluator()
{
}
///
/// Initializes a new instance of the BindingEvaluator class,
/// setting the initial binding to the provided parameter.
///
/// The initial string value binding.
public BindingEvaluator(Binding binding)
{
SetBinding(ValueProperty, binding);
}
///
/// Clears the data context so that the control does not keep a
/// reference to the last-looked up item.
///
public void ClearDataContext()
{
DataContext = null;
}
///
/// Updates the data context of the framework element and returns the
/// updated binding value.
///
/// The object to use as the data context.
/// If set to true, this parameter will
/// clear the data context immediately after retrieving the value.
/// Returns the evaluated T value of the bound dependency
/// property.
public T GetDynamicValue(object o, bool clearDataContext)
{
DataContext = o;
T value = Value;
if (clearDataContext)
{
DataContext = null;
}
return value;
}
///
/// Updates the data context of the framework element and returns the
/// updated binding value.
///
/// The object to use as the data context.
/// Returns the evaluated T value of the bound dependency
/// property.
public T GetDynamicValue(object o)
{
DataContext = o;
return Value;
}
}
}
================================================
FILE: WpfToolkit/Common/System/Windows/Controls/Extensions.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993] for details.
// All other rights reserved.
using System;
using System.Windows;
using System.Windows.Media;
namespace System.Windows.Controls.Extensions
{
///
/// This set of internal extension methods provide general solutions and
/// utilities in a small enough number to not warrant a dedicated extension
/// methods class.
///
internal static partial class Extensions
{
///
/// Inverts a Matrix. The Invert functionality on the Matrix type is
/// internal to the framework only. Since Matrix is a struct, an out
/// parameter must be presented.
///
/// The Matrix object.
/// The matrix to return by an output
/// parameter.
/// Returns a value indicating whether the type was
/// successfully inverted. If the determinant is 0.0, then it cannot
/// be inverted and the original instance will remain untouched.
public static bool Invert(this Matrix m, out Matrix outputMatrix)
{
double determinant = m.M11 * m.M22 - m.M12 * m.M21;
if (determinant == 0.0)
{
outputMatrix = m;
return false;
}
Matrix matCopy = m;
m.M11 = matCopy.M22 / determinant;
m.M12 = -1 * matCopy.M12 / determinant;
m.M21 = -1 * matCopy.M21 / determinant;
m.M22 = matCopy.M11 / determinant;
m.OffsetX = (matCopy.OffsetY * matCopy.M21 - matCopy.OffsetX * matCopy.M22) / determinant;
m.OffsetY = (matCopy.OffsetX * matCopy.M12 - matCopy.OffsetY * matCopy.M11) / determinant;
outputMatrix = m;
return true;
}
///
/// An implementation of the Contains member of string that takes in a
/// string comparison. The traditional .NET string Contains member uses
/// StringComparison.Ordinal.
///
/// The string.
/// The string value to search for.
/// The string comparison type.
/// Returns true when the substring is found.
public static bool Contains(this string s, string value, StringComparison comparison)
{
return s.IndexOf(value, comparison) >= 0;
}
}
}
================================================
FILE: WpfToolkit/Common/System/Windows/Controls/IUpdateVisualState.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993] for details.
// All other rights reserved.
using System;
using System.Diagnostics.CodeAnalysis;
namespace System.Windows.Controls
{
///
/// The IUpdateVisualState interface is used to provide the
/// InteractionHelper with access to the type's UpdateVisualState method.
///
[SuppressMessage("Microsoft.Design", "CA1064:ExceptionsShouldBePublic", Justification = "This is not an exception class.")]
internal interface IUpdateVisualState
{
///
/// Update the visual state of the control.
///
///
/// A value indicating whether to automatically generate transitions to
/// the new state, or instantly transition to the new state.
///
void UpdateVisualState(bool useTransitions);
}
}
================================================
FILE: WpfToolkit/Common/System/Windows/Controls/InteractionHelper.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993] for details.
// All other rights reserved.
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace System.Windows.Controls
{
///
/// The InteractionHelper provides controls with support for all of the
/// common interactions like mouse movement, mouse clicks, key presses,
/// etc., and also incorporates proper event semantics when the control is
/// disabled.
///
internal sealed partial class InteractionHelper
{
// TODO: Consult with user experience experts to validate the double
// click distance and time thresholds.
///
/// The threshold used to determine whether two clicks are temporally
/// local and considered a double click (or triple, quadruple, etc.).
/// 500 milliseconds is the default double click value on Windows.
/// This value would ideally be pulled form the system settings.
///
private const double SequentialClickThresholdInMilliseconds = 500.0;
///
/// The threshold used to determine whether two clicks are spatially
/// local and considered a double click (or triple, quadruple, etc.)
/// in pixels squared. We use pixels squared so that we can compare to
/// the distance delta without taking a square root.
///
private const double SequentialClickThresholdInPixelsSquared = 3.0 * 3.0;
///
/// Gets the control the InteractionHelper is targeting.
///
public Control Control { get; private set; }
///
/// Gets a value indicating whether the control has focus.
///
public bool IsFocused { get; private set; }
///
/// Gets a value indicating whether the mouse is over the control.
///
public bool IsMouseOver { get; private set; }
///
/// Gets a value indicating whether the read-only property is set.
///
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Linked file.")]
public bool IsReadOnly { get; private set; }
///
/// Gets a value indicating whether the mouse button is pressed down
/// over the control.
///
public bool IsPressed { get; private set; }
///
/// Gets or sets the last time the control was clicked.
///
///
/// The value is stored as Utc time because it is slightly more
/// performant than converting to local time.
///
private DateTime LastClickTime { get; set; }
///
/// Gets or sets the mouse position of the last click.
///
/// The value is relative to the control.
private Point LastClickPosition { get; set; }
///
/// Gets the number of times the control was clicked.
///
public int ClickCount { get; private set; }
///
/// Reference used to call UpdateVisualState on the base class.
///
private IUpdateVisualState _updateVisualState;
///
/// Initializes a new instance of the InteractionHelper class.
///
/// Control receiving interaction.
public InteractionHelper(Control control)
{
Debug.Assert(control != null, "control should not be null!");
Control = control;
_updateVisualState = control as IUpdateVisualState;
// Wire up the event handlers for events without a virtual override
control.Loaded += OnLoaded;
control.IsEnabledChanged += OnIsEnabledChanged;
}
#region UpdateVisualState
///
/// Update the visual state of the control.
///
///
/// A value indicating whether to automatically generate transitions to
/// the new state, or instantly transition to the new state.
///
///
/// UpdateVisualState works differently than the rest of the injected
/// functionality. Most of the other events are overridden by the
/// calling class which calls Allow, does what it wants, and then calls
/// Base. UpdateVisualState is the opposite because a number of the
/// methods in InteractionHelper need to trigger it in the calling
/// class. We do this using the IUpdateVisualState internal interface.
///
private void UpdateVisualState(bool useTransitions)
{
if (_updateVisualState != null)
{
_updateVisualState.UpdateVisualState(useTransitions);
}
}
///
/// Update the visual state of the control.
///
///
/// A value indicating whether to automatically generate transitions to
/// the new state, or instantly transition to the new state.
///
public void UpdateVisualStateBase(bool useTransitions)
{
// Handle the Common states
if (!Control.IsEnabled)
{
VisualStates.GoToState(Control, useTransitions, VisualStates.StateDisabled, VisualStates.StateNormal);
}
else if (IsReadOnly)
{
VisualStates.GoToState(Control, useTransitions, VisualStates.StateReadOnly, VisualStates.StateNormal);
}
else if (IsPressed)
{
VisualStates.GoToState(Control, useTransitions, VisualStates.StatePressed, VisualStates.StateMouseOver, VisualStates.StateNormal);
}
else if (IsMouseOver)
{
VisualStates.GoToState(Control, useTransitions, VisualStates.StateMouseOver, VisualStates.StateNormal);
}
else
{
VisualStates.GoToState(Control, useTransitions, VisualStates.StateNormal);
}
// Handle the Focused states
if (IsFocused)
{
VisualStates.GoToState(Control, useTransitions, VisualStates.StateFocused, VisualStates.StateUnfocused);
}
else
{
VisualStates.GoToState(Control, useTransitions, VisualStates.StateUnfocused);
}
}
#endregion UpdateVisualState
///
/// Handle the control's Loaded event.
///
/// The control.
/// Event arguments.
private void OnLoaded(object sender, RoutedEventArgs e)
{
UpdateVisualState(false);
}
///
/// Handle changes to the control's IsEnabled property.
///
/// The control.
/// Event arguments.
private void OnIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
bool enabled = (bool) e.NewValue;
if (!enabled)
{
IsPressed = false;
IsMouseOver = false;
IsFocused = false;
}
UpdateVisualState(true);
}
///
/// Handles changes to the control's IsReadOnly property.
///
/// The value of the property.
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Linked file.")]
public void OnIsReadOnlyChanged(bool value)
{
IsReadOnly = value;
if (!value)
{
IsPressed = false;
IsMouseOver = false;
IsFocused = false;
}
UpdateVisualState(true);
}
///
/// Update the visual state of the control when its template is changed.
///
public void OnApplyTemplateBase()
{
UpdateVisualState(false);
}
#region GotFocus
///
/// Check if the control's GotFocus event should be handled.
///
/// Event arguments.
///
/// A value indicating whether the event should be handled.
///
public bool AllowGotFocus(RoutedEventArgs e)
{
if (e == null)
{
throw new ArgumentNullException("e");
}
bool enabled = Control.IsEnabled;
if (enabled)
{
IsFocused = true;
}
return enabled;
}
///
/// Base implementation of the virtual GotFocus event handler.
///
public void OnGotFocusBase()
{
UpdateVisualState(true);
}
#endregion GotFocus
#region LostFocus
///
/// Check if the control's LostFocus event should be handled.
///
/// Event arguments.
///
/// A value indicating whether the event should be handled.
///
public bool AllowLostFocus(RoutedEventArgs e)
{
if (e == null)
{
throw new ArgumentNullException("e");
}
bool enabled = Control.IsEnabled;
if (enabled)
{
IsFocused = false;
}
return enabled;
}
///
/// Base implementation of the virtual LostFocus event handler.
///
public void OnLostFocusBase()
{
IsPressed = false;
UpdateVisualState(true);
}
#endregion LostFocus
#region MouseEnter
///
/// Check if the control's MouseEnter event should be handled.
///
/// Event arguments.
///
/// A value indicating whether the event should be handled.
///
public bool AllowMouseEnter(MouseEventArgs e)
{
if (e == null)
{
throw new ArgumentNullException("e");
}
bool enabled = Control.IsEnabled;
if (enabled)
{
IsMouseOver = true;
}
return enabled;
}
///
/// Base implementation of the virtual MouseEnter event handler.
///
public void OnMouseEnterBase()
{
UpdateVisualState(true);
}
#endregion MouseEnter
#region MouseLeave
///
/// Check if the control's MouseLeave event should be handled.
///
/// Event arguments.
///
/// A value indicating whether the event should be handled.
///
public bool AllowMouseLeave(MouseEventArgs e)
{
if (e == null)
{
throw new ArgumentNullException("e");
}
bool enabled = Control.IsEnabled;
if (enabled)
{
IsMouseOver = false;
}
return enabled;
}
///
/// Base implementation of the virtual MouseLeave event handler.
///
public void OnMouseLeaveBase()
{
UpdateVisualState(true);
}
#endregion MouseLeave
#region MouseLeftButtonDown
///
/// Check if the control's MouseLeftButtonDown event should be handled.
///
/// Event arguments.
///
/// A value indicating whether the event should be handled.
///
public bool AllowMouseLeftButtonDown(MouseButtonEventArgs e)
{
if (e == null)
{
throw new ArgumentNullException("e");
}
bool enabled = Control.IsEnabled;
if (enabled)
{
// Get the current position and time
DateTime now = DateTime.UtcNow;
Point position = e.GetPosition(Control);
// Compute the deltas from the last click
double timeDelta = (now - LastClickTime).TotalMilliseconds;
Point lastPosition = LastClickPosition;
double dx = position.X - lastPosition.X;
double dy = position.Y - lastPosition.Y;
double distance = dx * dx + dy * dy;
// Check if the values fall under the sequential click temporal
// and spatial thresholds
if (timeDelta < SequentialClickThresholdInMilliseconds &&
distance < SequentialClickThresholdInPixelsSquared)
{
// TODO: Does each click have to be within the single time
// threshold on WPF?
ClickCount++;
}
else
{
ClickCount = 1;
}
// Set the new position and time
LastClickTime = now;
LastClickPosition = position;
// Raise the event
IsPressed = true;
}
else
{
ClickCount = 1;
}
return enabled;
}
///
/// Base implementation of the virtual MouseLeftButtonDown event
/// handler.
///
public void OnMouseLeftButtonDownBase()
{
UpdateVisualState(true);
}
#endregion MouseLeftButtonDown
#region MouseLeftButtonUp
///
/// Check if the control's MouseLeftButtonUp event should be handled.
///
/// Event arguments.
///
/// A value indicating whether the event should be handled.
///
public bool AllowMouseLeftButtonUp(MouseButtonEventArgs e)
{
if (e == null)
{
throw new ArgumentNullException("e");
}
bool enabled = Control.IsEnabled;
if (enabled)
{
IsPressed = false;
}
return enabled;
}
///
/// Base implementation of the virtual MouseLeftButtonUp event handler.
///
public void OnMouseLeftButtonUpBase()
{
UpdateVisualState(true);
}
#endregion MouseLeftButtonUp
#region KeyDown
///
/// Check if the control's KeyDown event should be handled.
///
/// Event arguments.
///
/// A value indicating whether the event should be handled.
///
public bool AllowKeyDown(KeyEventArgs e)
{
if (e == null)
{
throw new ArgumentNullException("e");
}
return Control.IsEnabled;
}
#endregion KeyDown
#region KeyUp
///
/// Check if the control's KeyUp event should be handled.
///
/// Event arguments.
///
/// A value indicating whether the event should be handled.
///
public bool AllowKeyUp(KeyEventArgs e)
{
if (e == null)
{
throw new ArgumentNullException("e");
}
return Control.IsEnabled;
}
#endregion KeyUp
}
}
================================================
FILE: WpfToolkit/Common/System/Windows/Controls/ItemsControlHelper.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993] for details.
// All other rights reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
namespace System.Windows.Controls
{
///
/// The ItemContainerGenerator provides useful utilities for ItemsControls.
///
/// Preview
internal sealed partial class ItemsControlHelper
{
///
/// Gets or sets the ItemsControl being tracked by the
/// ItemContainerGenerator.
///
private ItemsControl ItemsControl { get; set; }
///
/// A Panel that is used as the ItemsHost of the ItemsControl. This
/// property will only be valid when the ItemsControl is live in the
/// tree and has generated containers for some of its items.
///
private Panel _itemsHost;
///
/// Gets a Panel that is used as the ItemsHost of the ItemsControl.
/// This property will only be valid when the ItemsControl is live in
/// the tree and has generated containers for some of its items.
///
internal Panel ItemsHost
{
get
{
// Lookup the ItemsHost if we haven't already cached it.
if (_itemsHost == null && ItemsControl != null && ItemsControl.ItemContainerGenerator != null)
{
// Get any live container
DependencyObject container = ItemsControl.ItemContainerGenerator.ContainerFromIndex(0);
if (container != null)
{
// Get the parent of the container
_itemsHost = VisualTreeHelper.GetParent(container) as Panel;
}
}
return _itemsHost;
}
}
///
/// A ScrollViewer that is used to scroll the items in the ItemsHost.
///
private ScrollViewer _scrollHost;
///
/// Gets a ScrollViewer that is used to scroll the items in the
/// ItemsHost.
///
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Code is linked into multiple projects.")]
internal ScrollViewer ScrollHost
{
get
{
if (_scrollHost == null)
{
Panel itemsHost = ItemsHost;
if (itemsHost != null)
{
for (DependencyObject obj = itemsHost; obj != ItemsControl && obj != null; obj = VisualTreeHelper.GetParent(obj))
{
ScrollViewer viewer = obj as ScrollViewer;
if (viewer != null)
{
_scrollHost = viewer;
break;
}
}
}
}
return _scrollHost;
}
}
///
/// Initializes a new instance of the ItemContainerGenerator.
///
///
/// The ItemsControl being tracked by the ItemContainerGenerator.
///
internal ItemsControlHelper(ItemsControl control)
{
Debug.Assert(control != null, "control cannot be null!");
ItemsControl = control;
}
///
/// Apply a control template to the ItemsControl.
///
internal void OnApplyTemplate()
{
// Clear the cached ItemsHost, ScrollHost
_itemsHost = null;
_scrollHost = null;
}
///
/// Prepares the specified container to display the specified item.
///
///
/// Container element used to display the specified item.
///
///
/// The ItemContainerStyle for the parent ItemsControl.
///
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Code is linked into multiple projects.")]
internal static void PrepareContainerForItemOverride(DependencyObject element, Style parentItemContainerStyle)
{
// Apply the ItemContainerStyle to the item
Control control = element as Control;
if (parentItemContainerStyle != null && control != null && control.Style == null)
{
control.SetValue(Control.StyleProperty, parentItemContainerStyle);
}
// Note: WPF also does preparation for ContentPresenter,
// ContentControl, HeaderedContentControl, and ItemsControl. Since
// we don't have any other ItemsControls using this
// ItemContainerGenerator, we've removed that code for now. It
// should be added back later when necessary.
}
///
/// Update the style of any generated items when the ItemContainerStyle
/// has been changed.
///
/// The ItemContainerStyle.
internal void UpdateItemContainerStyle(Style itemContainerStyle)
{
if (itemContainerStyle == null)
{
return;
}
Panel itemsHost = ItemsHost;
if (itemsHost == null || itemsHost.Children == null)
{
return;
}
foreach (UIElement element in itemsHost.Children)
{
FrameworkElement obj = element as FrameworkElement;
if (obj.Style == null)
{
obj.Style = itemContainerStyle;
}
}
}
///
/// Scroll the desired element into the ScrollHost's viewport.
///
/// Element to scroll into view.
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "File is linked across multiple projects and this method is used in some but not others.")]
internal void ScrollIntoView(FrameworkElement element)
{
// Get the ScrollHost
ScrollViewer scrollHost = ScrollHost;
if (scrollHost == null)
{
return;
}
// Get the position of the element relative to the ScrollHost
GeneralTransform transform = null;
try
{
transform = element.TransformToVisual(scrollHost);
}
catch (ArgumentException)
{
// Ignore failures when not in the visual tree
return;
}
Rect itemRect = new Rect(
transform.Transform(new Point()),
transform.Transform(new Point(element.ActualWidth, element.ActualHeight)));
// Scroll vertically
double verticalOffset = scrollHost.VerticalOffset;
double verticalDelta = 0;
double hostBottom = scrollHost.ViewportHeight;
double itemBottom = itemRect.Bottom;
if (hostBottom < itemBottom)
{
verticalDelta = itemBottom - hostBottom;
verticalOffset += verticalDelta;
}
double itemTop = itemRect.Top;
if (itemTop - verticalDelta < 0)
{
verticalOffset -= verticalDelta - itemTop;
}
scrollHost.ScrollToVerticalOffset(verticalOffset);
// Scroll horizontally
double horizontalOffset = scrollHost.HorizontalOffset;
double horizontalDelta = 0;
double hostRight = scrollHost.ViewportWidth;
double itemRight = itemRect.Right;
if (hostRight < itemRight)
{
horizontalDelta = itemRight - hostRight;
horizontalOffset += horizontalDelta;
}
double itemLeft = itemRect.Left;
if (itemLeft - horizontalDelta < 0)
{
horizontalOffset -= horizontalDelta - itemLeft;
}
scrollHost.ScrollToHorizontalOffset(horizontalOffset);
}
}
}
================================================
FILE: WpfToolkit/Common/System/Windows/Controls/VisualStates.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993] for details.
// All other rights reserved.
using System;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace System.Windows.Controls
{
///
/// Names and helpers for visual states in the controls.
///
internal static class VisualStates
{
#region GroupCommon
///
/// Common state group.
///
public const string GroupCommon = "CommonStates";
///
/// Normal state of the Common state group.
///
public const string StateNormal = "Normal";
///
/// Normal state of the Common state group.
///
public const string StateReadOnly = "ReadOnly";
///
/// MouseOver state of the Common state group.
///
public const string StateMouseOver = "MouseOver";
///
/// Pressed state of the Common state group.
///
public const string StatePressed = "Pressed";
///
/// Disabled state of the Common state group.
///
public const string StateDisabled = "Disabled";
#endregion GroupCommon
#region GroupFocus
///
/// Focus state group.
///
public const string GroupFocus = "FocusStates";
///
/// Unfocused state of the Focus state group.
///
public const string StateUnfocused = "Unfocused";
///
/// Focused state of the Focus state group.
///
public const string StateFocused = "Focused";
#endregion GroupFocus
#region GroupSelection
///
/// Selection state group.
///
public const string GroupSelection = "SelectionStates";
///
/// Selected state of the Selection state group.
///
public const string StateSelected = "Selected";
///
/// Unselected state of the Selection state group.
///
public const string StateUnselected = "Unselected";
///
/// Selected inactive state of the Selection state group.
///
public const string StateSelectedInactive = "SelectedInactive";
#endregion GroupSelection
#region GroupExpansion
///
/// Expansion state group.
///
public const string GroupExpansion = "ExpansionStates";
///
/// Expanded state of the Expansion state group.
///
public const string StateExpanded = "Expanded";
///
/// Collapsed state of the Expansion state group.
///
public const string StateCollapsed = "Collapsed";
#endregion GroupExpansion
#region GroupPopup
///
/// Popup state group.
///
public const string GroupPopup = "PopupStates";
///
/// Opened state of the Popup state group.
///
public const string StatePopupOpened = "PopupOpened";
///
/// Closed state of the Popup state group.
///
public const string StatePopupClosed = "PopupClosed";
#endregion
#region GroupValidation
///
/// ValidationStates state group.
///
public const string GroupValidation = "ValidationStates";
///
/// The valid state for the ValidationStates group.
///
public const string StateValid = "Valid";
///
/// Invalid, focused state for the ValidationStates group.
///
public const string StateInvalidFocused = "InvalidFocused";
///
/// Invalid, unfocused state for the ValidationStates group.
///
public const string StateInvalidUnfocused = "InvalidUnfocused";
#endregion
#region GroupExpandDirection
///
/// ExpandDirection state group.
///
public const string GroupExpandDirection = "ExpandDirectionStates";
///
/// Down expand direction state of ExpandDirection state group.
///
public const string StateExpandDown = "ExpandDown";
///
/// Up expand direction state of ExpandDirection state group.
///
public const string StateExpandUp = "ExpandUp";
///
/// Left expand direction state of ExpandDirection state group.
///
public const string StateExpandLeft = "ExpandLeft";
///
/// Right expand direction state of ExpandDirection state group.
///
public const string StateExpandRight = "ExpandRight";
#endregion
#region GroupHasItems
///
/// HasItems state group.
///
public const string GroupHasItems = "HasItemsStates";
///
/// HasItems state of the HasItems state group.
///
public const string StateHasItems = "HasItems";
///
/// NoItems state of the HasItems state group.
///
public const string StateNoItems = "NoItems";
#endregion GroupHasItems
#region GroupIncrease
///
/// Increment state group.
///
public const string GroupIncrease = "IncreaseStates";
///
/// State enabled for increment group.
///
public const string StateIncreaseEnabled = "IncreaseEnabled";
///
/// State disabled for increment group.
///
public const string StateIncreaseDisabled = "IncreaseDisabled";
#endregion GroupIncrease
#region GroupDecrease
///
/// Decrement state group.
///
public const string GroupDecrease = "DecreaseStates";
///
/// State enabled for decrement group.
///
public const string StateDecreaseEnabled = "DecreaseEnabled";
///
/// State disabled for decrement group.
///
public const string StateDecreaseDisabled = "DecreaseDisabled";
#endregion GroupDecrease
#region GroupIteractionMode
///
/// InteractionMode state group.
///
public const string GroupInteractionMode = "InteractionModeStates";
///
/// Edit of the DisplayMode state group.
///
public const string StateEdit = "Edit";
///
/// Display of the DisplayMode state group.
///
public const string StateDisplay = "Display";
#endregion GroupIteractionMode
#region GroupLocked
///
/// DisplayMode state group.
///
public const string GroupLocked = "LockedStates";
///
/// Edit of the DisplayMode state group.
///
public const string StateLocked = "Locked";
///
/// Display of the DisplayMode state group.
///
public const string StateUnlocked = "Unlocked";
#endregion GroupLocked
#region GroupActive
///
/// Active state.
///
public const string StateActive = "Active";
///
/// Inactive state.
///
public const string StateInactive = "Inactive";
///
/// Active state group.
///
public const string GroupActive = "ActiveStates";
#endregion GroupActive
#region GroupWatermark
///
/// Non-watermarked state.
///
public const string StateUnwatermarked = "Unwatermarked";
///
/// Watermarked state.
///
public const string StateWatermarked = "Watermarked";
///
/// Watermark state group.
///
public const string GroupWatermark = "WatermarkStates";
#endregion GroupWatermark
#region GroupCalendarButtonFocus
///
/// Unfocused state for Calendar Buttons.
///
public const string StateCalendarButtonUnfocused = "CalendarButtonUnfocused";
///
/// Focused state for Calendar Buttons.
///
public const string StateCalendarButtonFocused = "CalendarButtonFocused";
///
/// CalendarButtons Focus state group.
///
public const string GroupCalendarButtonFocus = "CalendarButtonFocusStates";
#endregion GroupCalendarButtonFocus
#region GroupBusyStatus
///
/// Busy state for BusyIndicator.
///
public const string StateBusy = "Busy";
///
/// Idle state for BusyIndicator.
///
public const string StateIdle = "Idle";
///
/// Busyness group name.
///
public const string GroupBusyStatus = "BusyStatusStates";
#endregion
#region GroupVisibility
///
/// Visible state name for BusyIndicator.
///
public const string StateVisible = "Visible";
///
/// Hidden state name for BusyIndicator.
///
public const string StateHidden = "Hidden";
///
/// BusyDisplay group.
///
public const string GroupVisibility = "VisibilityStates";
#endregion
///
/// Use VisualStateManager to change the visual state of the control.
///
///
/// Control whose visual state is being changed.
///
///
/// A value indicating whether to use transitions when updating the
/// visual state, or to snap directly to the new visual state.
///
///
/// Ordered list of state names and fallback states to transition into.
/// Only the first state to be found will be used.
///
public static void GoToState(Control control, bool useTransitions, params string[] stateNames)
{
Debug.Assert(control != null, "control should not be null!");
Debug.Assert(stateNames != null, "stateNames should not be null!");
Debug.Assert(stateNames.Length > 0, "stateNames should not be empty!");
foreach (string name in stateNames)
{
if (VisualStateManager.GoToState(control, name, useTransitions))
{
break;
}
}
}
///
/// Gets the implementation root of the Control.
///
/// The DependencyObject.
/// Returns the implementation root or null.
public static FrameworkElement GetImplementationRoot(DependencyObject dependencyObject)
{
Debug.Assert(dependencyObject != null, "DependencyObject should not be null.");
return (1 == VisualTreeHelper.GetChildrenCount(dependencyObject)) ?
VisualTreeHelper.GetChild(dependencyObject, 0) as FrameworkElement :
null;
}
///
/// This method tries to get the named VisualStateGroup for the
/// dependency object. The provided object's ImplementationRoot will be
/// looked up in this call.
///
/// The dependency object.
/// The visual state group's name.
/// Returns null or the VisualStateGroup object.
public static VisualStateGroup TryGetVisualStateGroup(DependencyObject dependencyObject, string groupName)
{
FrameworkElement root = GetImplementationRoot(dependencyObject);
if (root == null)
{
return null;
}
return VisualStateManager.GetVisualStateGroups(root)
.OfType()
.Where(group => string.CompareOrdinal(groupName, group.Name) == 0)
.FirstOrDefault();
}
}
}
================================================
FILE: WpfToolkit/Common/System/Windows/Controls/VisualTreeExtensions.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993] for details.
// All other rights reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Media;
namespace System.Windows.Controls
{
///
/// A static class providing methods for working with the visual tree.
///
internal static class VisualTreeExtensions
{
///
/// Retrieves all the visual children of a framework element.
///
/// The parent framework element.
/// The visual children of the framework element.
internal static IEnumerable GetVisualChildren(this DependencyObject parent)
{
Debug.Assert(parent != null, "The parent cannot be null.");
int childCount = VisualTreeHelper.GetChildrenCount(parent);
for (int counter = 0; counter < childCount; counter++)
{
yield return VisualTreeHelper.GetChild(parent, counter);
}
}
///
/// Retrieves all the logical children of a framework element using a
/// breadth-first search. A visual element is assumed to be a logical
/// child of another visual element if they are in the same namescope.
/// For performance reasons this method manually manages the queue
/// instead of using recursion.
///
/// The parent framework element.
/// The logical children of the framework element.
internal static IEnumerable GetLogicalChildrenBreadthFirst(this FrameworkElement parent)
{
Debug.Assert(parent != null, "The parent cannot be null.");
Queue queue =
new Queue(parent.GetVisualChildren().OfType());
while (queue.Count > 0)
{
FrameworkElement element = queue.Dequeue();
yield return element;
foreach (FrameworkElement visualChild in element.GetVisualChildren().OfType())
{
queue.Enqueue(visualChild);
}
}
}
}
}
================================================
FILE: WpfToolkit/Common/System/Windows/Controls/WeakEventListener.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993] for details.
// All other rights reserved.
using System.Diagnostics.CodeAnalysis;
namespace System.Windows.Controls
{
///
/// Implements a weak event listener that allows the owner to be garbage
/// collected if its only remaining link is an event handler.
///
/// Type of instance listening for the event.
/// Type of source for the event.
/// Type of event arguments for the event.
[SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Justification = "Used as link target in several projects.")]
internal class WeakEventListener where TInstance : class
{
///
/// WeakReference to the instance listening for the event.
///
private WeakReference _weakInstance;
///
/// Gets or sets the method to call when the event fires.
///
public Action OnEventAction { get; set; }
///
/// Gets or sets the method to call when detaching from the event.
///
public Action> OnDetachAction { get; set; }
///
/// Initializes a new instances of the WeakEventListener class.
///
/// Instance subscribing to the event.
public WeakEventListener(TInstance instance)
{
if (null == instance)
{
throw new ArgumentNullException("instance");
}
_weakInstance = new WeakReference(instance);
}
///
/// Handler for the subscribed event calls OnEventAction to handle it.
///
/// Event source.
/// Event arguments.
public void OnEvent(TSource source, TEventArgs eventArgs)
{
TInstance target = (TInstance)_weakInstance.Target;
if (null != target)
{
// Call registered action
if (null != OnEventAction)
{
OnEventAction(target, source, eventArgs);
}
}
else
{
// Detach from event
Detach();
}
}
///
/// Detaches from the subscribed event.
///
public void Detach()
{
if (null != OnDetachAction)
{
OnDetachAction(this);
OnDetachAction = null;
}
}
}
}
================================================
FILE: WpfToolkit/DataVisualization/AggregatedObservableCollection.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
namespace System.Windows.Controls.DataVisualization
{
///
/// Aggregated observable collection.
///
/// The type of the items in the observable collections.
///
internal class AggregatedObservableCollection : ReadOnlyObservableCollection
{
///
/// Initializes a new instance of an aggregated observable collection.
///
public AggregatedObservableCollection()
{
this.ChildCollections = new NoResetObservableCollection();
this.ChildCollections.CollectionChanged += new NotifyCollectionChangedEventHandler(ChildCollectionsCollectionChanged);
}
///
/// Rebuilds the list if a collection changes.
///
/// The source of the event.
/// Information about the event.
private void ChildCollectionsCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
Debug.Assert(e.Action != NotifyCollectionChangedAction.Reset, "Reset is not supported.");
if (e.Action == NotifyCollectionChangedAction.Add)
{
e.NewItems
.OfType()
.ForEachWithIndex((newCollection, index) =>
{
int startingIndex = GetStartingIndexOfCollectionAtIndex(e.NewStartingIndex + index);
foreach (T item in newCollection.OfType().Reverse())
{
this.Mutate(items => items.Insert(startingIndex, item));
}
INotifyCollectionChanged notifyCollectionChanged = newCollection as INotifyCollectionChanged;
if (notifyCollectionChanged != null)
{
notifyCollectionChanged.CollectionChanged += ChildCollectionCollectionChanged;
}
});
}
else if (e.Action == NotifyCollectionChangedAction.Remove)
{
foreach (IList oldCollection in e.OldItems)
{
INotifyCollectionChanged notifyCollectionChanged = oldCollection as INotifyCollectionChanged;
if (notifyCollectionChanged != null)
{
notifyCollectionChanged.CollectionChanged -= ChildCollectionCollectionChanged;
}
foreach (T item in oldCollection)
{
this.Mutate(items => items.Remove(item));
}
}
}
else if (e.Action == NotifyCollectionChangedAction.Replace)
{
foreach (IList oldCollection in e.OldItems)
{
INotifyCollectionChanged notifyCollectionChanged = oldCollection as INotifyCollectionChanged;
if (notifyCollectionChanged != null)
{
notifyCollectionChanged.CollectionChanged -= ChildCollectionCollectionChanged;
}
}
foreach (IList newCollection in e.NewItems)
{
INotifyCollectionChanged notifyCollectionChanged = newCollection as INotifyCollectionChanged;
if (notifyCollectionChanged != null)
{
notifyCollectionChanged.CollectionChanged += ChildCollectionCollectionChanged;
}
}
Rebuild();
}
}
///
/// Synchronizes the collection with changes made in a child collection.
///
/// The source of the event.
/// Information about the event.
private void ChildCollectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Debug.Assert(e.Action != NotifyCollectionChangedAction.Reset, "Reset is not supported.");
IList collectionSender = sender as IList;
if (e.Action == NotifyCollectionChangedAction.Add)
{
int startingIndex = GetStartingIndexOfCollectionAtIndex(ChildCollections.IndexOf(collectionSender));
e.NewItems
.OfType()
.ForEachWithIndex((item, index) =>
{
this.Mutate(that => that.Insert(startingIndex + e.NewStartingIndex + index, item));
});
}
else if (e.Action == NotifyCollectionChangedAction.Remove)
{
foreach (T item in e.OldItems.OfType())
{
this.Mutate(that => that.Remove(item));
}
}
else if (e.Action == NotifyCollectionChangedAction.Replace)
{
for (int cnt = 0; cnt < e.NewItems.Count; cnt++)
{
T oldItem = (T)e.OldItems[cnt];
T newItem = (T)e.NewItems[cnt];
int oldItemIndex = this.IndexOf(oldItem);
this.Mutate((that) =>
{
that[oldItemIndex] = newItem;
});
}
}
}
///
/// Returns the starting index of a collection in the aggregate
/// collection.
///
/// The starting index of a collection.
/// The starting index of the collection in the aggregate
/// collection.
private int GetStartingIndexOfCollectionAtIndex(int index)
{
return ChildCollections.OfType().Select(collection => collection.CastWrapper()).Take(index).SelectMany(collection => collection).Count();
}
///
/// Rebuild the list in the correct order when a child collection
/// changes.
///
private void Rebuild()
{
this.Mutate(that => that.Clear());
this.Mutate(that =>
{
IList items = ChildCollections.OfType().Select(collection => collection.CastWrapper()).SelectMany(collection => collection).ToList();
foreach (T item in items)
{
that.Add(item);
}
});
}
///
/// Gets child collections of the aggregated collection.
///
public ObservableCollection ChildCollections { get; private set; }
}
}
================================================
FILE: WpfToolkit/DataVisualization/AssemblyInfoShared.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System;
using System.Resources;
using System.Windows.Markup;
// WPF shared settings
[assembly: CLSCompliant(true)]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: XmlnsDefinition("clr-namespace:System.Windows.Controls.DataVisualization;assembly=DotNetProjects.DataVisualization.Toolkit", "System.Windows.Controls.DataVisualization")]
[assembly: XmlnsDefinition("clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=DotNetProjects.DataVisualization.Toolkit", "System.Windows.Controls.DataVisualization.Charting")]
[assembly: XmlnsPrefix("clr-namespace:System.Windows.Controls.DataVisualization;assembly=DotNetProjects.DataVisualization.Toolkit", "visualizationToolkit")]
[assembly: XmlnsPrefix("clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=DotNetProjects.DataVisualization.Toolkit", "chartingToolkit")]
#if !NO_XMLNSDEFINITION_URIS
[assembly: XmlnsPrefix("http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit", "toolkit")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit", "System.Windows.Controls.DataVisualization")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit", "System.Windows.Controls.DataVisualization.Charting")]
#endif
================================================
FILE: WpfToolkit/DataVisualization/Charting/AnimationSequence.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
namespace System.Windows.Controls.DataVisualization.Charting
{
///
/// Specifies the supported animation sequences.
///
/// Preview
public enum AnimationSequence
{
///
/// Animates all of the data points simultaneously.
///
Simultaneous = 0,
///
/// Animates the data points from first to last.
///
FirstToLast = 1,
///
/// Animates the data points from last to first.
///
LastToFirst = 2
}
}
================================================
FILE: WpfToolkit/DataVisualization/Charting/Axis/Axis.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Controls;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
namespace System.Windows.Controls.DataVisualization.Charting
{
///
/// An axis class used to determine the plot area coordinate of values.
///
public abstract class Axis : Control, IAxis
{
#region public AxisLocation Location
///
/// Gets or sets the axis location.
///
public AxisLocation Location
{
get { return (AxisLocation)GetValue(LocationProperty); }
set { SetValue(LocationProperty, value); }
}
///
/// Identifies the Location dependency property.
///
public static readonly DependencyProperty LocationProperty =
DependencyProperty.Register(
"Location",
typeof(AxisLocation),
typeof(Axis),
new PropertyMetadata(AxisLocation.Auto, OnLocationPropertyChanged));
///
/// LocationProperty property changed handler.
///
/// Axis that changed its Location.
/// Event arguments.
private static void OnLocationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis source = (Axis)d;
AxisLocation oldValue = (AxisLocation)e.OldValue;
AxisLocation newValue = (AxisLocation)e.NewValue;
source.OnLocationPropertyChanged(oldValue, newValue);
}
///
/// LocationProperty property changed handler.
///
/// Old value.
/// New value.
protected virtual void OnLocationPropertyChanged(AxisLocation oldValue, AxisLocation newValue)
{
RoutedPropertyChangedEventHandler handler = this.LocationChanged;
if (handler != null)
{
handler(this, new RoutedPropertyChangedEventArgs(oldValue, newValue));
}
}
///
/// This event is raised when the location property is changed.
///
public event RoutedPropertyChangedEventHandler LocationChanged;
#endregion public AxisLocation Location
///
/// Gets the list of child axes belonging to this axis.
///
public ObservableCollection DependentAxes { get; private set; }
#region public AxisOrientation Orientation
///
/// Gets or sets the orientation of the axis.
///
public AxisOrientation Orientation
{
get { return (AxisOrientation)GetValue(OrientationProperty); }
set { SetValue(OrientationProperty, value); }
}
///
/// Identifies the Orientation dependency property.
///
public static readonly DependencyProperty OrientationProperty =
DependencyProperty.Register(
"Orientation",
typeof(AxisOrientation),
typeof(Axis),
new PropertyMetadata(AxisOrientation.None, OnOrientationPropertyChanged));
///
/// OrientationProperty property changed handler.
///
/// Axis that changed its Orientation.
/// Event arguments.
private static void OnOrientationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis source = (Axis)d;
AxisOrientation oldValue = (AxisOrientation)e.OldValue;
AxisOrientation newValue = (AxisOrientation)e.NewValue;
source.OnOrientationPropertyChanged(oldValue, newValue);
}
///
/// OrientationProperty property changed handler.
///
/// Old value.
/// New value.
protected virtual void OnOrientationPropertyChanged(AxisOrientation oldValue, AxisOrientation newValue)
{
RoutedPropertyChangedEventHandler handler = OrientationChanged;
if (handler != null)
{
handler(this, new RoutedPropertyChangedEventArgs(oldValue, newValue));
}
}
///
/// This event is raised when the Orientation property is changed.
///
public event RoutedPropertyChangedEventHandler OrientationChanged;
#endregion public AxisOrientation Orientation
///
/// Raises the invalidated event.
///
/// Information about the event.
protected virtual void OnInvalidated(RoutedEventArgs args)
{
foreach (IAxisListener listener in RegisteredListeners)
{
listener.AxisInvalidated(this);
}
}
///
/// Gets or the collection of series that are using the Axis.
///
public ObservableCollection RegisteredListeners { get; private set; }
///
/// Returns a value indicating whether the axis can plot a value.
///
/// The value to plot.
/// A value indicating whether the axis can plot a value.
///
public abstract bool CanPlot(object value);
///
/// The plot area coordinate of a value.
///
/// The value for which to retrieve the plot area
/// coordinate.
/// The plot area coordinate.
public abstract UnitValue GetPlotAreaCoordinate(object value);
///
/// Instantiates a new instance of the Axis class.
///
protected Axis()
{
RegisteredListeners = new UniqueObservableCollection();
this.RegisteredListeners.CollectionChanged += RegisteredListenersCollectionChanged;
this.DependentAxes = new ObservableCollection();
this.DependentAxes.CollectionChanged += OnChildAxesCollectionChanged;
}
///
/// Child axes collection changed.
///
/// The source of the event.
/// Information about the event.
private void OnChildAxesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
this.OnDependentAxesCollectionChanged();
}
///
/// Child axes collection changed.
///
protected virtual void OnDependentAxesCollectionChanged()
{
}
///
/// This event is raised when the registered listeners collection is
/// changed.
///
/// The source of the event.
/// Information about the event.
private void RegisteredListenersCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.OldItems != null)
{
foreach (IAxisListener obj in e.OldItems)
{
OnObjectUnregistered(obj);
}
}
if (e.NewItems != null)
{
foreach (IAxisListener obj in e.NewItems)
{
OnObjectRegistered(obj);
}
}
}
///
/// This method is invoked when a series is registered.
///
/// The series that has been registered.
protected virtual void OnObjectRegistered(IAxisListener series)
{
}
///
/// This method is invoked when a series is unregistered.
///
/// The series that has been unregistered.
protected virtual void OnObjectUnregistered(IAxisListener series)
{
}
}
}
================================================
FILE: WpfToolkit/DataVisualization/Charting/Axis/AxisIntervalType.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
namespace System.Windows.Controls.DataVisualization.Charting
{
///
/// Specifies an interval type.
///
/// Preview
internal enum AxisIntervalType
{
///
/// Automatically determined by the ISeriesHost control.
///
Auto = 0,
///
/// The interval type is numerical.
///
Number = 1,
///
/// The interval type is years.
///
Years = 2,
///
/// The interval type is months.
///
Months = 3,
///
/// The interval type is weeks.
///
Weeks = 4,
///
/// The interval type is days.
///
Days = 5,
///
/// The interval type is hours.
///
Hours = 6,
///
/// The interval type is minutes.
///
Minutes = 7,
///
/// The interval type is seconds.
///
Seconds = 8,
///
/// The interval type is milliseconds.
///
Milliseconds = 9,
}
}
================================================
FILE: WpfToolkit/DataVisualization/Charting/Axis/AxisLabel.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace System.Windows.Controls.DataVisualization.Charting
{
///
/// A label used to display data in an axis.
///
public class AxisLabel : Control
{
#region public string StringFormat
///
/// Gets or sets the text string format.
///
public string StringFormat
{
get { return GetValue(StringFormatProperty) as string; }
set { SetValue(StringFormatProperty, value); }
}
///
/// Identifies the StringFormat dependency property.
///
public static readonly DependencyProperty StringFormatProperty =
DependencyProperty.Register(
"StringFormat",
typeof(string),
typeof(AxisLabel),
new PropertyMetadata(null, OnStringFormatPropertyChanged));
///
/// StringFormatProperty property changed handler.
///
/// AxisLabel that changed its StringFormat.
/// Event arguments.
private static void OnStringFormatPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
AxisLabel source = (AxisLabel)d;
string newValue = (string)e.NewValue;
source.OnStringFormatPropertyChanged(newValue);
}
///
/// StringFormatProperty property changed handler.
///
/// New value.
protected virtual void OnStringFormatPropertyChanged(string newValue)
{
UpdateFormattedContent();
}
#endregion public string StringFormat
#region public string FormattedContent
///
/// Gets the formatted content property.
///
public string FormattedContent
{
get { return GetValue(FormattedContentProperty) as string; }
protected set { SetValue(FormattedContentProperty, value); }
}
///
/// Identifies the FormattedContent dependency property.
///
public static readonly DependencyProperty FormattedContentProperty =
DependencyProperty.Register(
"FormattedContent",
typeof(string),
typeof(AxisLabel),
new PropertyMetadata(null));
#endregion public string FormattedContent
///
/// Initializes the static members of the AxisLabel class.
///
[SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline", Justification = "Dependency properties are initialized in-line.")]
static AxisLabel()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(AxisLabel), new FrameworkPropertyMetadata(typeof(AxisLabel)));
}
///
/// Instantiates a new instance of the AxisLabel class.
///
public AxisLabel()
{
this.SetBinding(FormattedContentProperty, new Binding { Converter = new StringFormatConverter(), ConverterParameter = StringFormat ?? "{0}" });
}
///
/// Updates the formatted text.
///
protected virtual void UpdateFormattedContent()
{
this.SetBinding(FormattedContentProperty, new Binding { Converter = new StringFormatConverter(), ConverterParameter = StringFormat ?? "{0}" });
}
}
}
================================================
FILE: WpfToolkit/DataVisualization/Charting/Axis/AxisLocation.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
namespace System.Windows.Controls.DataVisualization.Charting
{
///
/// Axis position.
///
public enum AxisLocation
{
///
/// Location is determined automatically.
///
Auto,
///
/// Left in the series host area.
///
Left,
///
/// Top in the series host area.
///
Top,
///
/// Right in the series host area.
///
Right,
///
/// Bottom of the series host area.
///
Bottom,
}
}
================================================
FILE: WpfToolkit/DataVisualization/Charting/Axis/AxisOrientation.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
namespace System.Windows.Controls.DataVisualization.Charting
{
///
/// Specifies the orientation of an axis.
///
/// Preview
public enum AxisOrientation
{
///
/// Orientation is automatically set.
///
None,
///
/// Indicates the axis plots along the X axis.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "X", Justification = "X is the expected terminology.")]
X,
///
/// Indicates the axis plots along the Y axis.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Y", Justification = "Y is the expected terminology.")]
Y,
}
}
================================================
FILE: WpfToolkit/DataVisualization/Charting/Axis/CategoryAxis.cs
================================================
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Windows.Shapes;
namespace System.Windows.Controls.DataVisualization.Charting
{
///
/// An axis that displays categories.
///
[StyleTypedProperty(Property = "GridLineStyle", StyleTargetType = typeof(Line))]
[StyleTypedProperty(Property = "MajorTickMarkStyle", StyleTargetType = typeof(Line))]
[StyleTypedProperty(Property = "AxisLabelStyle", StyleTargetType = typeof(AxisLabel))]
[StyleTypedProperty(Property = "TitleStyle", StyleTargetType = typeof(Title))]
[TemplatePart(Name = AxisGridName, Type = typeof(Grid))]
[TemplatePart(Name = AxisTitleName, Type = typeof(Title))]
public class CategoryAxis : DisplayAxis, ICategoryAxis
{
///
/// A pool of major tick marks.
///
private ObjectPool _majorTickMarkPool;
///
/// A pool of labels.
///
private ObjectPool _labelPool;
#region public CategorySortOrder SortOrder
///
/// Gets or sets the sort order used for the categories.
///
public CategorySortOrder SortOrder
{
get { return (CategorySortOrder)GetValue(SortOrderProperty); }
set { SetValue(SortOrderProperty, value); }
}
///
/// Identifies the SortOrder dependency property.
///
public static readonly DependencyProperty SortOrderProperty =
DependencyProperty.Register(
"SortOrder",
typeof(CategorySortOrder),
typeof(CategoryAxis),
new PropertyMetadata(CategorySortOrder.None, OnSortOrderPropertyChanged));
///
/// SortOrderProperty property changed handler.
///
/// CategoryAxis that changed its SortOrder.
/// Event arguments.
private static void OnSortOrderPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CategoryAxis source = (CategoryAxis)d;
source.OnSortOrderPropertyChanged();
}
///
/// SortOrderProperty property changed handler.
///
private void OnSortOrderPropertyChanged()
{
Invalidate();
}
#endregion public CategorySortOrder SortOrder
///
/// Gets or sets a list of categories to display.
///
private IList