@@ -209,6 +209,17 @@ public double ContentMinWidth
209
209
set { SetValue ( ContentMinWidthProperty , value ) ; }
210
210
}
211
211
212
+ public static readonly DependencyProperty RelativeHorizontalOffsetProperty
213
+ = DependencyProperty . Register (
214
+ nameof ( RelativeHorizontalOffset ) , typeof ( double ) , typeof ( ComboBoxPopup ) ,
215
+ new FrameworkPropertyMetadata ( default ( double ) ) ) ;
216
+
217
+ public double RelativeHorizontalOffset
218
+ {
219
+ get => ( double ) GetValue ( RelativeHorizontalOffsetProperty ) ;
220
+ set => SetValue ( RelativeHorizontalOffsetProperty , value ) ;
221
+ }
222
+
212
223
public ComboBoxPopup ( )
213
224
{
214
225
CustomPopupPlacementCallback = ComboBoxCustomPopupPlacementCallback ;
@@ -230,7 +241,7 @@ protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
230
241
private void SetupVisiblePlacementWidth ( IEnumerable < DependencyObject > visualAncestry )
231
242
{
232
243
var parent = visualAncestry . OfType < Panel > ( ) . ElementAt ( 1 ) ;
233
- VisiblePlacementWidth = TreeHelper . GetVisibleWidth ( ( FrameworkElement ) PlacementTarget , parent ) ;
244
+ VisiblePlacementWidth = TreeHelper . GetVisibleWidth ( ( FrameworkElement ) PlacementTarget , parent , FlowDirection ) ;
234
245
}
235
246
236
247
private CustomPopupPlacement [ ] ComboBoxCustomPopupPlacementCallback (
@@ -240,13 +251,13 @@ private CustomPopupPlacement[] ComboBoxCustomPopupPlacementCallback(
240
251
241
252
SetupVisiblePlacementWidth ( visualAncestry ) ;
242
253
243
- var data = GetPositioningData ( visualAncestry , popupSize , targetSize , offset ) ;
254
+ var data = GetPositioningData ( visualAncestry , popupSize , targetSize ) ;
244
255
var preferUpIfSafe = data . LocationY + data . PopupSize . Height > data . ScreenHeight ;
245
256
246
257
if ( ClassicMode
247
- || data . LocationX + data . PopupSize . Width - data . RealOffsetX > data . ScreenWidth
248
- || data . LocationX - data . RealOffsetX < 0
249
- || ! preferUpIfSafe && data . LocationY - Math . Abs ( data . NewDownY ) < 0 )
258
+ || data . PopupLocationX + data . PopupSize . Width > data . ScreenWidth
259
+ || data . PopupLocationX < 0
260
+ || ! preferUpIfSafe && data . LocationY + data . NewDownY < 0 )
250
261
{
251
262
SetCurrentValue ( PopupPlacementProperty , ComboBoxPopupPlacement . Classic ) ;
252
263
return new [ ] { GetClassicPopupPlacement ( this , data ) } ;
@@ -272,7 +283,7 @@ private void SetChildTemplateIfNeed(ControlTemplate template)
272
283
}
273
284
}
274
285
275
- private PositioningData GetPositioningData ( IEnumerable < DependencyObject > visualAncestry , Size popupSize , Size targetSize , Point offset )
286
+ private PositioningData GetPositioningData ( IEnumerable < DependencyObject > visualAncestry , Size popupSize , Size targetSize )
276
287
{
277
288
var locationFromScreen = PlacementTarget . PointToScreen ( new Point ( 0 , 0 ) ) ;
278
289
@@ -290,15 +301,11 @@ private PositioningData GetPositioningData(IEnumerable<DependencyObject> visualA
290
301
var upVerticalOffsetIndependent = DpiHelper . TransformToDeviceY ( mainVisual , UpVerticalOffset ) ;
291
302
var newUpY = upVerticalOffsetIndependent - popupSize . Height + targetSize . Height ;
292
303
var newDownY = DpiHelper . TransformToDeviceY ( mainVisual , DownVerticalOffset ) ;
293
-
294
- double offsetX ;
295
- const int rtlHorizontalOffset = 20 ;
296
-
304
+ var offsetX = DpiHelper . TransformToDeviceX ( mainVisual , RelativeHorizontalOffset ) ;
297
305
if ( FlowDirection == FlowDirection . LeftToRight )
298
- offsetX = DpiHelper . TransformToDeviceX ( mainVisual , offset . X ) ;
306
+ offsetX = Round ( offsetX ) ;
299
307
else
300
- offsetX = DpiHelper . TransformToDeviceX ( mainVisual ,
301
- offset . X - targetSize . Width - rtlHorizontalOffset ) ;
308
+ offsetX = Math . Truncate ( offsetX - targetSize . Width ) ;
302
309
303
310
return new PositioningData (
304
311
mainVisual , offsetX ,
@@ -308,6 +315,8 @@ private PositioningData GetPositioningData(IEnumerable<DependencyObject> visualA
308
315
screenHeight , screenWidth ) ;
309
316
}
310
317
318
+ private static double Round ( double val ) => val < 0 ? ( int ) ( val - 0.5 ) : ( int ) ( val + 0.5 ) ;
319
+
311
320
private static PropertyChangedCallback CreateTemplatePropertyChangedCallback ( ComboBoxPopupPlacement popupPlacement )
312
321
{
313
322
return delegate ( DependencyObject d , DependencyPropertyChangedEventArgs e )
@@ -379,7 +388,7 @@ private struct PositioningData
379
388
public double OffsetX { get ; }
380
389
public double NewUpY { get ; }
381
390
public double NewDownY { get ; }
382
- public double RealOffsetX => ( PopupSize . Width - TargetSize . Width ) / 2.0 ;
391
+ public double PopupLocationX => LocationX + OffsetX ;
383
392
public Size PopupSize { get ; }
384
393
public Size TargetSize { get ; }
385
394
public double LocationX { get ; }
@@ -390,9 +399,9 @@ private struct PositioningData
390
399
public PositioningData ( Visual mainVisual , double offsetX , double newUpY , double newDownY , Size popupSize , Size targetSize , double locationX , double locationY , double screenHeight , double screenWidth )
391
400
{
392
401
MainVisual = mainVisual ;
393
- OffsetX = offsetX ;
394
- NewUpY = newUpY ;
395
- NewDownY = newDownY ;
402
+ OffsetX = Round ( offsetX ) ;
403
+ NewUpY = Round ( newUpY ) ;
404
+ NewDownY = Round ( newDownY ) ;
396
405
PopupSize = popupSize ; TargetSize = targetSize ;
397
406
LocationX = locationX ; LocationY = locationY ;
398
407
ScreenWidth = screenWidth ; ScreenHeight = screenHeight ;
0 commit comments