@@ -37,6 +37,8 @@ static MultiSelectionComboBox()
3737 TextProperty . OverrideMetadata ( typeof ( MultiSelectionComboBox ) , new FrameworkPropertyMetadata ( string . Empty , FrameworkPropertyMetadataOptions . BindsTwoWayByDefault | FrameworkPropertyMetadataOptions . Journal , OnTextChanged ) ) ;
3838 CommandManager . RegisterClassCommandBinding ( typeof ( MultiSelectionComboBox ) , new CommandBinding ( ClearContentCommand , ExecutedClearContentCommand , CanExecuteClearContentCommand ) ) ;
3939 CommandManager . RegisterClassCommandBinding ( typeof ( MultiSelectionComboBox ) , new CommandBinding ( RemoveItemCommand , RemoveItemCommand_Executed , RemoveItemCommand_CanExecute ) ) ;
40+
41+ CommandManager . RegisterClassCommandBinding ( typeof ( MultiSelectionComboBox ) , new CommandBinding ( SelectAllCommand , new ExecutedRoutedEventHandler ( OnSelectAll ) , new CanExecuteRoutedEventHandler ( OnQueryStatusSelectAll ) ) ) ;
4042 }
4143
4244 public MultiSelectionComboBox ( )
@@ -68,6 +70,11 @@ public MultiSelectionComboBox()
6870 private bool shouldAddItems ; // Defines if the MSCB should add new items from text input. Don't set this to true while input is pending. We cannot know how long the user needs for typing.
6971 private bool IsSyncingSelectedItems ; // true if syncing in one or the other direction already running
7072 private DispatcherTimer ? _updateSelectedItemsFromTextTimer ;
73+ private static readonly RoutedUICommand SelectAllCommand
74+ = new RoutedUICommand ( "Select All" ,
75+ nameof ( SelectAllCommand ) ,
76+ typeof ( MultiSelectionComboBox ) ,
77+ new InputGestureCollection ( ) { new KeyGesture ( Key . A , ModifierKeys . Control ) } ) ;
7178
7279 #endregion
7380
@@ -547,6 +554,193 @@ public void ResetEditableText(bool forceUpdate = false)
547554 }
548555 }
549556
557+
558+ /// <summary>
559+ /// Identifies the <see cref="IsDropDownHeaderVisible"/> dependency property.
560+ /// </summary>
561+ public static readonly DependencyProperty IsDropDownHeaderVisibleProperty =
562+ DependencyProperty . Register ( nameof ( IsDropDownHeaderVisible ) ,
563+ typeof ( bool ) ,
564+ typeof ( MultiSelectionComboBox ) ,
565+ new PropertyMetadata ( BooleanBoxes . FalseBox ) ) ;
566+
567+ /// <summary>
568+ /// Gets or Sets if the Header in the DropDown is visible
569+ /// </summary>
570+ public bool IsDropDownHeaderVisible
571+ {
572+ get { return ( bool ) GetValue ( IsDropDownHeaderVisibleProperty ) ; }
573+ set { SetValue ( IsDropDownHeaderVisibleProperty , value ) ; }
574+ }
575+
576+
577+ /// <summary>
578+ /// Identifies the <see cref="DropDownHeaderContent"/> dependency property.
579+ /// </summary>
580+ public static readonly DependencyProperty DropDownHeaderContentProperty =
581+ DependencyProperty . Register ( nameof ( DropDownHeaderContent ) ,
582+ typeof ( object ) ,
583+ typeof ( MultiSelectionComboBox ) ,
584+ new PropertyMetadata ( null ) ) ;
585+
586+ /// <summary>
587+ /// Gets or Sets the content of the DropDown-Header
588+ /// </summary>
589+ public object ? DropDownHeaderContent
590+ {
591+ get { return ( object ? ) GetValue ( DropDownHeaderContentProperty ) ; }
592+ set { SetValue ( DropDownHeaderContentProperty , value ) ; }
593+ }
594+
595+
596+ /// <summary>
597+ /// Identifies the <see cref="DropDownHeaderContentTemplate"/> dependency property.
598+ /// </summary>
599+ public static readonly DependencyProperty DropDownHeaderContentTemplateProperty =
600+ DependencyProperty . Register ( nameof ( DropDownHeaderContentTemplate ) ,
601+ typeof ( DataTemplate ) ,
602+ typeof ( MultiSelectionComboBox ) ,
603+ new PropertyMetadata ( null ) ) ;
604+
605+ /// <summary>
606+ /// Gets or Sets the content template of the DropDown-Header
607+ /// </summary>
608+ public DataTemplate ? DropDownHeaderContentTemplate
609+ {
610+ get { return ( DataTemplate ? ) GetValue ( DropDownHeaderContentTemplateProperty ) ; }
611+ set { SetValue ( DropDownHeaderContentTemplateProperty , value ) ; }
612+ }
613+
614+ /// <summary>
615+ /// Identifies the <see cref="DropDownHeaderContentTemplateSelector"/> dependency property.
616+ /// </summary>
617+ public static readonly DependencyProperty DropDownHeaderContentTemplateSelectorProperty =
618+ DependencyProperty . Register ( nameof ( DropDownHeaderContentTemplateSelector ) ,
619+ typeof ( DataTemplateSelector ) ,
620+ typeof ( MultiSelectionComboBox ) ,
621+ new PropertyMetadata ( null ) ) ;
622+
623+ /// <summary>
624+ /// Gets or Sets the content template selector of the DropDown-Header
625+ /// </summary>
626+ public DataTemplateSelector ? DropDownHeaderContentTemplateSelector
627+ {
628+ get { return ( DataTemplateSelector ? ) GetValue ( DropDownHeaderContentTemplateSelectorProperty ) ; }
629+ set { SetValue ( DropDownHeaderContentTemplateSelectorProperty , value ) ; }
630+ }
631+
632+ /// <summary>
633+ /// Identifies the <see cref="DropDownHeaderContentStringFormat"/> dependency property.
634+ /// </summary>
635+ public static readonly DependencyProperty DropDownHeaderContentStringFormatProperty =
636+ DependencyProperty . Register ( nameof ( DropDownHeaderContentStringFormat ) ,
637+ typeof ( string ) ,
638+ typeof ( MultiSelectionComboBox ) ,
639+ new PropertyMetadata ( null ) ) ;
640+
641+ /// <summary>
642+ /// Gets or Sets the content string format of the DropDown-Header
643+ /// </summary>
644+ public string ? DropDownHeaderContentStringFormat
645+ {
646+ get { return ( string ? ) GetValue ( DropDownHeaderContentStringFormatProperty ) ; }
647+ set { SetValue ( DropDownHeaderContentStringFormatProperty , value ) ; }
648+ }
649+
650+
651+ /// <summary>
652+ /// Identifies the <see cref="IsDropDownFooterVisible"/> dependency property.
653+ /// </summary>
654+ public static readonly DependencyProperty IsDropDownFooterVisibleProperty =
655+ DependencyProperty . Register ( nameof ( IsDropDownFooterVisible ) ,
656+ typeof ( bool ) ,
657+ typeof ( MultiSelectionComboBox ) ,
658+ new PropertyMetadata ( BooleanBoxes . FalseBox ) ) ;
659+
660+ /// <summary>
661+ /// Gets or Sets if the Footer in the DropDown is visible
662+ /// </summary>
663+ public bool IsDropDownFooterVisible
664+ {
665+ get { return ( bool ) GetValue ( IsDropDownFooterVisibleProperty ) ; }
666+ set { SetValue ( IsDropDownFooterVisibleProperty , value ) ; }
667+ }
668+
669+
670+ /// <summary>
671+ /// Identifies the <see cref="DropDownFooterContent"/> dependency property.
672+ /// </summary>
673+ public static readonly DependencyProperty DropDownFooterContentProperty =
674+ DependencyProperty . Register ( nameof ( DropDownFooterContent ) ,
675+ typeof ( object ) ,
676+ typeof ( MultiSelectionComboBox ) ,
677+ new PropertyMetadata ( null ) ) ;
678+
679+ /// <summary>
680+ /// Gets or Sets the content of the DropDown-Footer
681+ /// </summary>
682+ public object ? DropDownFooterContent
683+ {
684+ get { return ( object ? ) GetValue ( DropDownFooterContentProperty ) ; }
685+ set { SetValue ( DropDownFooterContentProperty , value ) ; }
686+ }
687+
688+
689+ /// <summary>
690+ /// Identifies the <see cref="DropDownFooterContentTemplate"/> dependency property.
691+ /// </summary>
692+ public static readonly DependencyProperty DropDownFooterContentTemplateProperty =
693+ DependencyProperty . Register ( nameof ( DropDownFooterContentTemplate ) ,
694+ typeof ( DataTemplate ) ,
695+ typeof ( MultiSelectionComboBox ) ,
696+ new PropertyMetadata ( null ) ) ;
697+
698+ /// <summary>
699+ /// Gets or Sets the content template of the DropDown-Footer
700+ /// </summary>
701+ public DataTemplate ? DropDownFooterContentTemplate
702+ {
703+ get { return ( DataTemplate ? ) GetValue ( DropDownFooterContentTemplateProperty ) ; }
704+ set { SetValue ( DropDownFooterContentTemplateProperty , value ) ; }
705+ }
706+
707+
708+ /// <summary>
709+ /// Identifies the <see cref="DropDownFooterContentTemplateSelector"/> dependency property.
710+ /// </summary>
711+ public static readonly DependencyProperty DropDownFooterContentTemplateSelectorProperty =
712+ DependencyProperty . Register ( nameof ( DropDownFooterContentTemplateSelector ) ,
713+ typeof ( DataTemplateSelector ) ,
714+ typeof ( MultiSelectionComboBox ) ,
715+ new PropertyMetadata ( null ) ) ;
716+
717+ /// <summary>
718+ /// Gets or Sets the content template selector of the DropDown-Footer
719+ /// </summary>
720+ public DataTemplateSelector ? DropDownFooterContentTemplateSelector
721+ {
722+ get { return ( DataTemplateSelector ? ) GetValue ( DropDownFooterContentTemplateSelectorProperty ) ; }
723+ set { SetValue ( DropDownFooterContentTemplateSelectorProperty , value ) ; }
724+ }
725+
726+ /// <summary>
727+ /// Identifies the <see cref="DropDownFooterContentStringFormat"/> dependency property.
728+ /// </summary>
729+ public static readonly DependencyProperty DropDownFooterContentStringFormatProperty =
730+ DependencyProperty . Register ( nameof ( DropDownFooterContentStringFormat ) ,
731+ typeof ( string ) ,
732+ typeof ( MultiSelectionComboBox ) ,
733+ new PropertyMetadata ( null ) ) ;
734+
735+ /// <summary>
736+ /// Gets or Sets the content string format of the DropDown-Footer
737+ /// </summary>
738+ public string ? DropDownFooterContentStringFormat
739+ {
740+ get { return ( string ? ) GetValue ( DropDownFooterContentStringFormatProperty ) ; }
741+ set { SetValue ( DropDownFooterContentStringFormatProperty , value ) ; }
742+ }
743+
550744 #endregion
551745
552746 #region Methods
@@ -1541,7 +1735,7 @@ private void SelectItemHelper(int startIndex, int increment, int stopIndex)
15411735 // IsSelectable and IsEnabled on the item and wrapper.
15421736 var item = this . Items [ i ] ;
15431737 var container = this . ItemContainerGenerator . ContainerFromIndex ( i ) ;
1544- if ( this . IsSelectableHelper ( item ) && this . IsSelectableHelper ( container ) )
1738+ if ( IsSelectableHelper ( item ) && IsSelectableHelper ( container ) )
15451739 {
15461740 this . SelectedIndex = i ;
15471741 this . UpdateEditableText ( true ) ; // We force the update of the text
@@ -1552,7 +1746,7 @@ private void SelectItemHelper(int startIndex, int increment, int stopIndex)
15521746 }
15531747
15541748 // adopted from original ComoBox
1555- private bool IsSelectableHelper ( object o )
1749+ private static bool IsSelectableHelper ( object o )
15561750 {
15571751 var d = o as DependencyObject ;
15581752 // If o is not a DependencyObject, it is just a plain
@@ -1566,9 +1760,44 @@ private bool IsSelectableHelper(object o)
15661760 return ( bool ) d . GetValue ( IsEnabledProperty ) ;
15671761 }
15681762
1569- #endregion
1763+ /// <summary>
1764+ /// Select all the items
1765+ /// </summary>
1766+ public void SelectAll ( )
1767+ {
1768+ PART_PopupListBox ? . SelectAll ( ) ;
1769+ }
1770+
1771+ private static void OnSelectAll ( object target , ExecutedRoutedEventArgs args )
1772+ {
1773+ if ( target is MultiSelectionComboBox comboBox )
1774+ {
1775+ comboBox . SelectAll ( ) ;
1776+ }
1777+ }
1778+
1779+ private static void OnQueryStatusSelectAll ( object target , CanExecuteRoutedEventArgs args )
1780+ {
1781+ if ( target is MultiSelectionComboBox comboBox )
1782+ {
1783+ args . CanExecute
1784+ = comboBox . SelectionMode == SelectionMode . Extended
1785+ && comboBox . IsDropDownOpen
1786+ && ! ( comboBox . PART_EditableTextBox ? . IsKeyboardFocused ?? false ) ;
1787+ }
1788+ }
1789+
1790+ /// <summary>
1791+ /// Clears all of the selected items.
1792+ /// </summary>
1793+ public void UnselectAll ( )
1794+ {
1795+ PART_PopupListBox ? . UnselectAll ( ) ;
1796+ }
1797+
1798+ #endregion
15701799
1571- #region Events
1800+ #region Events
15721801
15731802#if NET5_0_OR_GREATER
15741803 private void SelectedItemsImpl_CollectionChanged ( object ? sender , NotifyCollectionChangedEventArgs e )
0 commit comments