1010
1111namespace MaterialDesignThemes . Wpf
1212{
13- public class ComboBoxPopup : Popup
13+ internal enum ComboBoxPopupPlacement
1414 {
15+ Undefined ,
16+ Down ,
17+ Up ,
18+ Classic
19+ }
20+
21+ internal class ComboBoxPopup : Popup
22+ {
23+ #region UpContentTemplate property
24+
1525 public static readonly DependencyProperty UpContentTemplateProperty
1626 = DependencyProperty . Register ( nameof ( UpContentTemplate ) ,
1727 typeof ( ControlTemplate ) ,
@@ -24,6 +34,10 @@ public ControlTemplate UpContentTemplate
2434 set { SetValue ( UpContentTemplateProperty , value ) ; }
2535 }
2636
37+ #endregion
38+
39+ #region DownContentTemplate region
40+
2741 public static readonly DependencyProperty DownContentTemplateProperty
2842 = DependencyProperty . Register ( nameof ( DownContentTemplate ) ,
2943 typeof ( ControlTemplate ) ,
@@ -36,18 +50,26 @@ public ControlTemplate DownContentTemplate
3650 set { SetValue ( DownContentTemplateProperty , value ) ; }
3751 }
3852
39- public static readonly DependencyProperty DefaultContentTemplateProperty
40- = DependencyProperty . Register ( nameof ( DefaultContentTemplate ) ,
53+ #endregion
54+
55+ #region ClassicContentTemplate property
56+
57+ public static readonly DependencyProperty ClassicContentTemplateProperty
58+ = DependencyProperty . Register ( nameof ( ClassicContentTemplate ) ,
4159 typeof ( ControlTemplate ) ,
4260 typeof ( ComboBoxPopup ) ,
4361 new UIPropertyMetadata ( null ) ) ;
4462
45- public ControlTemplate DefaultContentTemplate
63+ public ControlTemplate ClassicContentTemplate
4664 {
47- get { return ( ControlTemplate ) GetValue ( DefaultContentTemplateProperty ) ; }
48- set { SetValue ( DefaultContentTemplateProperty , value ) ; }
65+ get { return ( ControlTemplate ) GetValue ( ClassicContentTemplateProperty ) ; }
66+ set { SetValue ( ClassicContentTemplateProperty , value ) ; }
4967 }
5068
69+ #endregion
70+
71+ #region UpVerticalOffset property
72+
5173 public static readonly DependencyProperty UpVerticalOffsetProperty
5274 = DependencyProperty . Register ( nameof ( UpVerticalOffset ) ,
5375 typeof ( double ) ,
@@ -60,6 +82,10 @@ public double UpVerticalOffset
6082 set { SetValue ( UpVerticalOffsetProperty , value ) ; }
6183 }
6284
85+ #endregion
86+
87+ #region DownVerticalOffset property
88+
6389 public static readonly DependencyProperty DownVerticalOffsetProperty
6490 = DependencyProperty . Register ( nameof ( DownVerticalOffset ) ,
6591 typeof ( double ) ,
@@ -72,6 +98,24 @@ public double DownVerticalOffset
7298 set { SetValue ( DownVerticalOffsetProperty , value ) ; }
7399 }
74100
101+ #endregion
102+
103+ #region PopupPlacement property
104+
105+ public static readonly DependencyProperty PopupPlacementProperty
106+ = DependencyProperty . Register ( nameof ( PopupPlacement ) ,
107+ typeof ( ComboBoxPopupPlacement ) ,
108+ typeof ( ComboBoxPopup ) ,
109+ new PropertyMetadata ( ComboBoxPopupPlacement . Undefined , PopupPlacementPropertyChangedCallback ) ) ;
110+
111+ public ComboBoxPopupPlacement PopupPlacement
112+ {
113+ get { return ( ComboBoxPopupPlacement ) GetValue ( PopupPlacementProperty ) ; }
114+ set { SetValue ( PopupPlacementProperty , value ) ; }
115+ }
116+
117+ #endregion
118+
75119 #region Background property
76120
77121 private static readonly DependencyPropertyKey BackgroundPropertyKey =
@@ -127,17 +171,6 @@ public ComboBoxPopup()
127171 this . CustomPopupPlacementCallback = ComboBoxCustomPopupPlacementCallback ;
128172 }
129173
130- private void SetChildTemplateIfNeed ( ControlTemplate template )
131- {
132- var contentControl = Child as ContentControl ;
133- if ( contentControl == null ) throw new InvalidOperationException ( "Child must be ContentControl" ) ;
134-
135- if ( ! ReferenceEquals ( contentControl . Template , template ) )
136- {
137- contentControl . Template = template ;
138- }
139- }
140-
141174 private void SetupBackground ( IEnumerable < DependencyObject > visualAncestry )
142175 {
143176 var background = visualAncestry
@@ -191,7 +224,7 @@ private CustomPopupPlacement[] ComboBoxCustomPopupPlacementCallback(
191224 if ( locationX + popupSize . Width - realOffsetX > screenWidth
192225 || locationX - realOffsetX < 0 )
193226 {
194- SetChildTemplateIfNeed ( DefaultContentTemplate ) ;
227+ PopupPlacement = ComboBoxPopupPlacement . Classic ;
195228
196229 var defaultVerticalOffsetIndepent = DpiHelper . TransformToDeviceY ( mainVisual , DefaultVerticalOffset ) ;
197230 var newY = locationY + popupSize . Height > screenHeight
@@ -203,7 +236,7 @@ private CustomPopupPlacement[] ComboBoxCustomPopupPlacementCallback(
203236
204237 if ( locationY + popupSize . Height > screenHeight )
205238 {
206- SetChildTemplateIfNeed ( UpContentTemplate ) ;
239+ PopupPlacement = ComboBoxPopupPlacement . Up ;
207240
208241 var upVerticalOffsetIndepent = DpiHelper . TransformToDeviceY ( mainVisual , UpVerticalOffset ) ;
209242 var newY = upVerticalOffsetIndepent - popupSize . Height + targetSize . Height ;
@@ -212,13 +245,53 @@ private CustomPopupPlacement[] ComboBoxCustomPopupPlacementCallback(
212245 }
213246 else
214247 {
215- SetChildTemplateIfNeed ( DownContentTemplate ) ;
248+ PopupPlacement = ComboBoxPopupPlacement . Down ;
216249
217250 var downVerticalOffsetIndepent = DpiHelper . TransformToDeviceY ( mainVisual , DownVerticalOffset ) ;
218251 var newY = downVerticalOffsetIndepent ;
219252
220253 return new [ ] { new CustomPopupPlacement ( new Point ( offsetX , newY ) , PopupPrimaryAxis . None ) } ;
221254 }
222255 }
256+
257+ private void SetChildTemplateIfNeed ( ControlTemplate template )
258+ {
259+ var contentControl = Child as ContentControl ;
260+ if ( contentControl == null ) throw new InvalidOperationException ( "Child must be ContentControl" ) ;
261+
262+ if ( ! ReferenceEquals ( contentControl . Template , template ) )
263+ {
264+ contentControl . Template = template ;
265+ }
266+ }
267+
268+ private void SetChildTemplate ( ComboBoxPopupPlacement placement )
269+ {
270+ switch ( placement )
271+ {
272+ case ComboBoxPopupPlacement . Classic :
273+ SetChildTemplateIfNeed ( ClassicContentTemplate ) ;
274+ return ;
275+ case ComboBoxPopupPlacement . Down :
276+ SetChildTemplateIfNeed ( DownContentTemplate ) ;
277+ return ;
278+ case ComboBoxPopupPlacement . Up :
279+ SetChildTemplateIfNeed ( UpContentTemplate ) ;
280+ return ;
281+ default :
282+ throw new NotImplementedException ( $ "Unexpected value { placement } of the { nameof ( PopupPlacement ) } property inside the { nameof ( ComboBoxPopup ) } control.") ;
283+ }
284+ }
285+
286+ private static void PopupPlacementPropertyChangedCallback ( DependencyObject d , DependencyPropertyChangedEventArgs e )
287+ {
288+ var popup = d as ComboBoxPopup ;
289+ if ( popup == null ) return ;
290+
291+ if ( ! ( e . NewValue is ComboBoxPopupPlacement ) ) return ;
292+ var placement = ( ComboBoxPopupPlacement ) e . NewValue ;
293+
294+ popup . SetChildTemplate ( placement ) ;
295+ }
223296 }
224297}
0 commit comments