この質問を完全なコードで解決することにしました。他の人がコードを実行できるように、奇妙な動作だと思うことを示すテストケースを作成しました。
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 を変更すると、スクロールしても図面が正しくセンタリングされなくなります。巨大なサイズですべてがグリッチするのはなぜですか? 大量のコンテンツに対応するには、独自のスクロールビューアーをコーディングする必要がありますか?それとも回避策はありますか?