0

この質問を完全なコードで解決することにしました。他の人がコードを実行できるように、奇妙な動作だと思うことを示すテストケースを作成しました。

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 を変更すると、スクロールしても図面が正しくセンタリングされなくなります。巨大なサイズですべてがグリッチするのはなぜですか? 大量のコンテンツに対応するには、独自のスクロールビューアーをコーディングする必要がありますか?それとも回避策はありますか?

4

1 に答える 1