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

1

所以一个朋友终于帮我解决了这个问题。即使我使用双打进行计算,WPF 也使用直接 x 进行绘图。直接 x 受浮点数限制。通过在 wiki 上检查浮点数的尾数,我发现我超过了浮点数的尾数值,因此该值不再准确。

于 2013-10-10T18:58:05.737 回答