@@ -931,16 +931,19 @@ private void OnAnchorOperation(bool isAnchorOperationPending)
931
931
// situations where the viewport size has changed)
932
932
if (!success)
933
933
{
934
+ double computedOffset, maxOffset;
934
935
if (isHorizontal)
935
936
{
936
- success = DoubleUtil.GreaterThanOrClose( _scrollData._computedOffset.X,
937
- _scrollData._extent.Width - _scrollData._viewport.Width) ;
937
+ computedOffset = _scrollData._computedOffset.X;
938
+ maxOffset = _scrollData._extent.Width - _scrollData._viewport.Width;
938
939
}
939
940
else
940
941
{
941
- success = DoubleUtil.GreaterThanOrClose( _scrollData._computedOffset.Y,
942
- _scrollData._extent.Height - _scrollData._viewport.Height) ;
942
+ computedOffset = _scrollData._computedOffset.Y;
943
+ maxOffset = _scrollData._extent.Height - _scrollData._viewport.Height;
943
944
}
945
+ success = LayoutDoubleUtil.LessThan(maxOffset, computedOffset) ||
946
+ LayoutDoubleUtil.AreClose(maxOffset, computedOffset);
944
947
}
945
948
}
946
949
}
@@ -973,21 +976,22 @@ private void OnAnchorOperation(bool isAnchorOperationPending)
973
976
else
974
977
{
975
978
bool remeasure = false;
976
- double actualOffset, expectedOffset;
979
+ double actualOffset, expectedOffset, maxOffset ;
977
980
978
981
if (isHorizontal)
979
982
{
980
983
_scrollData._computedOffset.X = prevFirstContainerOffset - prevFirstContainerOffsetFromViewport;
981
984
982
985
actualOffset = _scrollData._computedOffset.X + actualDistanceBetweenViewports;
983
986
expectedOffset = _scrollData._computedOffset.X + _scrollData._expectedDistanceBetweenViewports;
987
+ maxOffset = _scrollData._extent.Width - _scrollData._viewport.Width;
984
988
985
- if (DoubleUtil .LessThan(expectedOffset, 0) || DoubleUtil.GreaterThan(expectedOffset, _scrollData._extent.Width - _scrollData._viewport.Width ))
989
+ if (LayoutDoubleUtil .LessThan(expectedOffset, 0) || LayoutDoubleUtil.LessThan(maxOffset, expectedOffset ))
986
990
{
987
991
// the condition can fail due to estimated sizes in subtrees that contribute
988
992
// to FindScrollOffset(_scrollData._firstContainerInViewport) but not to
989
993
// _scrollData._extent. If that happens, remeasure.
990
- if (DoubleUtil .AreClose(actualOffset, 0) || DoubleUtil .AreClose(actualOffset, _scrollData._extent.Width - _scrollData._viewport.Width ))
994
+ if (LayoutDoubleUtil .AreClose(actualOffset, 0) || LayoutDoubleUtil .AreClose(actualOffset, maxOffset ))
991
995
{
992
996
_scrollData._computedOffset.X = actualOffset;
993
997
_scrollData._offset.X = actualOffset;
@@ -1010,13 +1014,14 @@ private void OnAnchorOperation(bool isAnchorOperationPending)
1010
1014
1011
1015
actualOffset = _scrollData._computedOffset.Y + actualDistanceBetweenViewports;
1012
1016
expectedOffset = _scrollData._computedOffset.Y + _scrollData._expectedDistanceBetweenViewports;
1017
+ maxOffset = _scrollData._extent.Height - _scrollData._viewport.Height;
1013
1018
1014
- if (DoubleUtil .LessThan(expectedOffset, 0) || DoubleUtil.GreaterThan(expectedOffset, _scrollData._extent.Height - _scrollData._viewport.Height ))
1019
+ if (LayoutDoubleUtil .LessThan(expectedOffset, 0) || LayoutDoubleUtil.LessThan(maxOffset, expectedOffset ))
1015
1020
{
1016
1021
// the condition can fail due to estimated sizes in subtrees that contribute
1017
1022
// to FindScrollOffset(_scrollData._firstContainerInViewport) but not to
1018
1023
// _scrollData._extent. If that happens, remeasure.
1019
- if (DoubleUtil .AreClose(actualOffset, 0) || DoubleUtil .AreClose(actualOffset, _scrollData._extent.Height - _scrollData._viewport.Height ))
1024
+ if (LayoutDoubleUtil .AreClose(actualOffset, 0) || LayoutDoubleUtil .AreClose(actualOffset, maxOffset ))
1020
1025
{
1021
1026
_scrollData._computedOffset.Y = actualOffset;
1022
1027
_scrollData._offset.Y = actualOffset;
@@ -2824,11 +2829,11 @@ private Size MeasureOverrideImpl(Size constraint,
2824
2829
ref scrollGeneration);
2825
2830
2826
2831
if (ItemsChangedDuringMeasure)
2827
- {
2828
- // if the Items collection changed, our state is now invalid. Start over.
2829
- remeasure = true;
2830
- goto EscapeMeasure;
2831
- }
2832
+ {
2833
+ // if the Items collection changed, our state is now invalid. Start over.
2834
+ remeasure = true;
2835
+ goto EscapeMeasure;
2836
+ }
2832
2837
}
2833
2838
}
2834
2839
@@ -2873,11 +2878,11 @@ private Size MeasureOverrideImpl(Size constraint,
2873
2878
ref scrollGeneration);
2874
2879
2875
2880
if (ItemsChangedDuringMeasure)
2876
- {
2877
- // if the Items collection changed, our state is now invalid. Start over.
2878
- remeasure = true;
2879
- goto EscapeMeasure;
2880
- }
2881
+ {
2882
+ // if the Items collection changed, our state is now invalid. Start over.
2883
+ remeasure = true;
2884
+ goto EscapeMeasure;
2885
+ }
2881
2886
}
2882
2887
}
2883
2888
@@ -12321,6 +12326,12 @@ private void IdentifyTrace(ItemsControl ic, VirtualizingStackPanel vsp)
12321
12326
"ScrollUnit:", VirtualizingPanel.GetScrollUnit(ic),
12322
12327
"CacheLen:", VirtualizingPanel.GetCacheLength(ic), VirtualizingPanel.GetCacheLengthUnit(ic));
12323
12328
12329
+ DpiScale dpiScale = vsp.GetDpi();
12330
+ AddTrace(null, ScrollTraceOp.ID, _nullInfo,
12331
+ "DPIScale:", dpiScale.DpiScaleX, dpiScale.DpiScaleY,
12332
+ "UseLayoutRounding:", vsp.UseLayoutRounding,
12333
+ "Rounding Quantum:", 1.0/dpiScale.DpiScaleY);
12334
+
12324
12335
AddTrace(null, ScrollTraceOp.ID, _nullInfo,
12325
12336
"CanContentScroll:", ScrollViewer.GetCanContentScroll(ic),
12326
12337
"IsDeferredScrolling:", ScrollViewer.GetIsDeferredScrollingEnabled(ic),
0 commit comments