Unable to render oversized UI element correctly
- Dominant language
- C#
- Stars
- 7.7k
- Forks
- 1.3k
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 61
Description
### Description
Potentially related topics:
> Why the Visual.VisualOffset is double type but run the compositor in floats? #5389
Q: Can we replace the MIL code with `double`? Or provide an enum type to control whether calculations use `float` or `double`?
I am developing timeline-related controls. If zoomed into frame mode view with each frame scale set to 500px, a 1-hour segment would span a width of `500px * 24fps * 3600s = 43,200,000 (≈2^25, 43 million)`. The element does not render correctly, appearing to lose precision and exhibit ghosting.
https://github.com/user-attachments/assets/7b46c586-e995-40ce-833d-2430f4289fea
https://github.com/user-attachments/assets/2cb307fa-af62-44be-8d5f-e95bdd3e0f04
### Reproduction Steps
mini demo: https://github.com/CodingOctocat/LargeViewRenderError
```xaml
```
```cs
public partial class MainWindow : Window
{
private AdornerLayer _adornerLayer = null!;
private bool _isSelecting;
private SelectionBoxAdorner? _selectionBoxAdorner;
private Point _startPoint;
public MainWindow()
{
InitializeComponent();
}
// 鼠标按下事件,开始选区
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
// 只有左键点击时才开始
if (e.ButtonState == MouseButtonState.Pressed && e.ChangedButton == MouseButton.Left)
{
_startPoint = e.GetPosition(canvas);
_isSelecting = true;
// 创建 SelectionBoxAdorner 并添加到 AdornerLayer
_selectionBoxAdorner = new SelectionBoxAdorner(canvas, _startPoint);
_adornerLayer.Add(_selectionBoxAdorner);
}
}
// 鼠标移动事件,更新选区大小
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (_isSelecting && _selectionBoxAdorner != null)
{
var currentPoint = e.GetPosition(canvas);
_selectionBoxAdorner.UpdateEndPoint(currentPoint);
Debug.WriteLine(">>> " + currentPoint);
}
}
// 鼠标松开事件,结束选区
private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
{
if (_isSelecting)
{
_isSelecting = false;
if (_selectionBoxAdorner != null)
{
_adornerLayer.Remove(_selectionBoxAdorner);
}
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
_adornerLayer = AdornerLayer.GetAdornerLayer(canvas); // 获取 AdornerLayer
}
}
```
```cs
public class SelectionBoxAdorner : Adorner
{
private readonly Pen _border;
private Point _end;
private Point _start;
public Brush BorderBrush { get; set; } = Brushes.DodgerBlue;
public Brush Fill { get; set; }
public SelectionBoxAdorner(UIElement adornedElement, Point start) : base(adornedElement)
{
BorderBrush = Brushes.DodgerBlue;
BorderBrush.Freeze();
Fill = new SolidColorBrush(Color.FromArgb(50, 0, 120, 215));
Fill.Freeze();
_border = new(BorderBrush, 1);
_start = start;
_end = start;
IsHitTestVisible = false;
// 测试
UseLayoutRounding = true;
SnapsToDevicePixels = true;
}
public Rect GetSelectionRect()
{
return new Rect(_start, _end);
}
public void UpdateEndPoint(Point end)
{
_end = end;
_end.X = Math.Max(_end.X, 0);
_end.Y = Math.Max(_end.Y, 0);
InvalidateVisual();
}
protected override void OnRender(DrawingContext dc)
{
var rect = GetSelectionRect();
dc.DrawRectangle(Fill, _border, rect);
}
}
```
### Expected behavior
Correctly render elements larger than 2^21 pixels.
### Actual behavior
Elements larger than 2^21px cannot be rendered correctly. Issues such as loss of precision, screen flickering, and ghosting may occur.
# Test:
## 2^23: Rendering error
## 2^22: Rendering imperfect
## 2^21: Perfect rendering
### Regression?
_No response_
### Known Workarounds
Using IScrollInfo + UI virtualization.
### Impact
_No response_
### Configuration
- .NET9
- Win11 24h2
- x64
### Other information
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.