-
Notifications
You must be signed in to change notification settings - Fork 803
Open
Labels
Description
Describe the bug
The ExtentChanged event is unexpectedly triggered when manipulating the scroll thumb of a ScrollView containing an ItemsRepeater. This occurs intermittently under specific DPI scaling and resolution conditions.
Steps to reproduce the bug
- On Windows 11, set the display scaling to 125% or 175% and resolution to 3840x2160.
- Build and launch the sample code provided below.
- Slowly slide the scroll thumb to the bottom.
- Slowly slide the scroll thumb to the top.
- Repeat steps 3 and 4 approximately 10 times.
Result: The debug output log shows that theExtentChangedevent is triggered unintentionally.
Expected behavior
The ExtentChanged event should not occur during scroll thumb operations. It is expected to fire only when the content's extent (size) changes, not during scrolling.
Screenshots
(No screenshots available; the issue is observable in the debug output log. See "Log Examples" in Additional Context for sample logs.)
NuGet package version
WinUI 3 - Windows App SDK 1.7.0: 1.7.250310001
Windows version
Windows 11 (24H2): Build 26100
Additional context
Actual Behavior:
- At 3840x2160 resolution, with scaling at 125% (DPI 120) and 175% (DPI 168), the
ExtentChangedevent occurs intermittently during scrolling. ExtentHeightexhibits slight fluctuations (e.g., 504000.0 ↔ 504000.8 at 125%, 502856.6 ↔ 502857.2 at 175%).- No occurrences at scaling 100%, 150%, 200%, 225%, 250%, 300%, 350% (tested at 3840x2160).
- No occurrence at 1920x1080 resolution with 175% scaling.
- Note: The issue is less likely to occur with fast thumb movement but is more frequent with slow movement. It may frequently occur at specific scroll positions (e.g., Offset around 502343.2).
Sample Code:
pch.h
#pragma once
#include <windows.h>
#include <unknwn.h>
#include <restrictederrorinfo.h>
#include <hstring.h>
#undef GetCurrentTime
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.ApplicationModel.Activation.h>
#include <winrt/Microsoft.UI.Composition.h>
#include <winrt/Microsoft.UI.Xaml.h>
#include <winrt/Microsoft.UI.Xaml.Controls.h>
#include <winrt/Microsoft.UI.Xaml.Controls.Primitives.h>
#include <winrt/Microsoft.UI.Xaml.Data.h>
#include <winrt/Microsoft.UI.Xaml.Interop.h>
#include <winrt/Microsoft.UI.Xaml.Markup.h>
#include <winrt/Microsoft.UI.Xaml.Media.h>
#include <winrt/Microsoft.UI.Xaml.Navigation.h>
#include <winrt/Microsoft.UI.Xaml.Shapes.h>
#include <winrt/Microsoft.UI.Dispatching.h>
#include <wil/cppwinrt_helpers.h>
#include <winrt/Microsoft.UI.Interop.h>
#include <microsoft.ui.xaml.window.h>
#include <winrt/Microsoft.UI.Windowing.h>MainWindow.xaml.h
#pragma once
#include "MainWindow.g.h"
namespace winrt::ScrollViewDpiTest::implementation
{
struct SimpleElementFactory : implements<SimpleElementFactory, Microsoft::UI::Xaml::IElementFactory>
{
Microsoft::UI::Xaml::UIElement GetElement(Microsoft::UI::Xaml::ElementFactoryGetArgs const& args);
void RecycleElement(Microsoft::UI::Xaml::ElementFactoryRecycleArgs const& args) {}
};
struct MainWindow : MainWindowT<MainWindow>
{
MainWindow();
void OnExtentChanged(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& args);
private:
Microsoft::UI::Xaml::Controls::ScrollView m_scrollView{ nullptr };
HWND GetWindowHandle();
};
}
namespace winrt::ScrollViewDpiTest::factory_implementation
{
struct MainWindow : MainWindowT<MainWindow, implementation::MainWindow>
{
};
}MainWindow.xaml.cpp
#include "pch.h"
#include "MainWindow.xaml.h"
#if __has_include("MainWindow.g.cpp")
#include "MainWindow.g.cpp"
#endif
using namespace winrt;
using namespace Microsoft::UI::Xaml;
namespace winrt::ScrollViewDpiTest::implementation
{
Microsoft::UI::Xaml::UIElement SimpleElementFactory::GetElement(Microsoft::UI::Xaml::ElementFactoryGetArgs const& args)
{
auto textBlock = Controls::TextBlock();
textBlock.Height(50);
textBlock.Text(args.Data().as<hstring>());
return textBlock;
}
MainWindow::MainWindow()
{
InitializeComponent();
auto rootGrid = Controls::Grid();
m_scrollView = Controls::ScrollView();
auto itemsRepeater = Controls::ItemsRepeater();
auto items = winrt::single_threaded_observable_vector<hstring>();
for (int i = 0; i < 10000; ++i)
{
items.Append(L"Item " + to_hstring(i));
}
itemsRepeater.ItemsSource(items);
auto elementFactory = make<SimpleElementFactory>();
itemsRepeater.ItemTemplate(elementFactory);
m_scrollView.Content(itemsRepeater);
m_scrollView.ExtentChanged({ this, &MainWindow::OnExtentChanged });
rootGrid.Children().Append(m_scrollView);
Content(rootGrid);
HWND hWnd = GetWindowHandle();
if (hWnd)
{
ShowWindow(hWnd, SW_MAXIMIZE);
}
}
void MainWindow::OnExtentChanged(Windows::Foundation::IInspectable const& /*sender*/, Windows::Foundation::IInspectable const& /*args*/)
{
double extentHeight = m_scrollView.ExtentHeight();
double viewportHeight = m_scrollView.ViewportHeight();
double verticalOffset = m_scrollView.VerticalOffset();
SYSTEMTIME st;
GetLocalTime(&st);
wchar_t buffer[256];
swprintf_s(buffer, 256, L"[ExtentChanged] [%04d-%02d-%02d %02d:%02d:%02d.%03d] ExtentHeight: %.1f, ViewportHeight: %.1f, Offset: %.1f\n",
st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
extentHeight, viewportHeight, verticalOffset);
OutputDebugStringW(buffer);
}
HWND MainWindow::GetWindowHandle()
{
auto windowNative = try_as<::IWindowNative>();
HWND hWnd{ nullptr };
if (windowNative)
{
windowNative->get_WindowHandle(&hWnd);
}
return hWnd;
}
}MainWindow.xaml
<?xml version="1.0" encoding="utf-8"?>
<Window
x:Class="ScrollViewDpiTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ScrollViewDpiTest"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="ScrollViewDpiTest">
</Window>Log Examples:
- Scale 125% (3840x2160):
[ExtentChanged] [2025-03-29 18:05:43.243] ExtentHeight: 504000.8, ViewportHeight: 1656.8, Offset: 294477.1
[ExtentChanged] [2025-03-29 18:05:43.287] ExtentHeight: 504000.0, ViewportHeight: 1656.8, Offset: 295230.2
[ExtentChanged] [2025-03-29 18:05:44.032] ExtentHeight: 504000.8, ViewportHeight: 1656.8, Offset: 502343.2
[ExtentChanged] [2025-03-29 18:05:44.371] ExtentHeight: 504000.0, ViewportHeight: 1656.8, Offset: 502343.2
- Scale 175% (3840x2160):
[ExtentChanged] [2025-03-29 18:10:55.538] ExtentHeight: 502856.6, ViewportHeight: 1163.4, Offset: 178621.6
[ExtentChanged] [2025-03-29 18:10:55.573] ExtentHeight: 502857.2, ViewportHeight: 1163.4, Offset: 178621.6
[ExtentChanged] [2025-03-29 18:10:58.743] ExtentHeight: 502856.6, ViewportHeight: 1163.4, Offset: 501693.7
[ExtentChanged] [2025-03-29 18:10:58.775] ExtentHeight: 502857.2, ViewportHeight: 1163.4, Offset: 501693.7
Additional Information:
- "The issue occurs at non-integer multiples of DPI 96 (125%, 175%) but not at integer or near-integer multiples (100%, 150%, 200%, etc.), though it may also depend on resolution."
- "At 3840x2160, the issue occurs at 125% and 175%, but not at 1920x1080 with 175%. Comprehensive testing across other resolutions has not been conducted, so it may not occur at different resolutions."
- "This could be due to a calculation error in scaling, potentially causing issues with the virtualization of
ItemsRepeaterand its interaction withScrollView, particularly noticeable on high-resolution displays with slow scrolling."
Reactions are currently unavailable