我决定用完整的代码来回答这个问题。我创建了一个测试用例,只是展示了我认为奇怪的行为,以便其他人可以运行代码。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;
namespace Test
{
public class TestSizeVisual: FrameworkElement
{
public double MinimumXInDIPs
{
get { return (double)GetValue(MinimumXInDIPsProperty); }
set
{
SetValue(MinimumXInDIPsProperty, value);
}
}
public static readonly DependencyProperty MinimumXInDIPsProperty =
DependencyProperty.Register("MinimumXInDIPs",
typeof(double), typeof(TestSizeVisual),
new FrameworkPropertyMetadata(new double(), new PropertyChangedCallback(Redraw)));
public double ViewportWidth
{
get { return (double)GetValue(ViewportWidthProperty); }
set
{
SetValue(ViewportWidthProperty, value);
}
}
public static readonly DependencyProperty ViewportWidthProperty =
DependencyProperty.Register("ViewportWidth",
typeof(double), typeof(TestSizeVisual),
new FrameworkPropertyMetadata(new double(), FrameworkPropertyMetadataOptions.AffectsMeasure));
VisualCollection visuals;
protected override Size MeasureOverride(Size availableSize)
{
return new Size(50000000000, 50);
}
public TestSizeVisual()
{
visuals = new VisualCollection(this);
this.Loaded += new RoutedEventHandler(TestSizeVisual_Loaded);
}
void TestSizeVisual_Loaded(object sender, RoutedEventArgs e)
{
DrawSignal();
}
private static void Redraw(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TestSizeVisual sg = d as TestSizeVisual;
if (sg != null && sg.IsLoaded)
{
sg.DrawSignal();
}
}
private void DrawSignal()
{
DrawingVisual signalbox = new DrawingVisual();
using (DrawingContext dc = signalbox.RenderOpen())
{
dc.DrawRectangle(Brushes.Orange, new Pen(Brushes.Black, 2), new Rect(new Point(0, 0), new Point(1000000000, ActualHeight)));
dc.DrawRectangle(Brushes.Purple, new Pen(Brushes.Black, 2), new Rect(new Point(MinimumXInDIPs, 2), new Point(MinimumXInDIPs + 10, 6)));
dc.DrawRectangle(Brushes.Purple, new Pen(Brushes.Black, 2), new Rect(new Point(MinimumXInDIPs + ViewportWidth - 10, 2), new Point(MinimumXInDIPs + ViewportWidth, 6)));
dc.DrawLine(new Pen(Brushes.Black, 2), new Point(MinimumXInDIPs, 10),
new Point(MinimumXInDIPs + ViewportWidth, 10));
}
visuals.Add(signalbox);
InvalidateVisual();
}
protected override Visual GetVisualChild(int index)
{
return visuals[index];
}
protected override int VisualChildrenCount
{
get
{
return visuals.Count;
}
}
}
}
xaml 文件如下所示:
<ScrollViewer
x:Name="scrollviewer1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Left"
HorizontalScrollBarVisibility="Visible"
VerticalScrollBarVisibility="Visible"
>
<test:TestSizeVisual
MinimumXInDIPs="{Binding ElementName=scrollviewer1, Path=HorizontalOffset}"
ViewportWidth="{Binding ElementName=scrollviewer1, Path=ViewportWidth}"
/>
</ScrollViewer>
当您滚动小尺寸的 testsizevisual 时,矩形和线条在屏幕上保持居中。但是,一旦我将 measureoverride 更改为返回一个巨大的尺寸,滚动不再导致图形正确居中。为什么所有东西都会以大尺寸出现故障?我是否需要编写自己的滚动查看器以容纳大量内容,或者是否有解决方法?