WPF是scrollviewer的水平偏移,在大值时是否准确?

时间:2013-10-09 22:30:40

标签: c# wpf scrollviewer

我决定用完整的代码来解决这个问题。我创建了一个测试用例,只是展示了我认为奇怪的行为,以便其他人可以运行代码。

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时,矩形和线条会在屏幕上居中。但是,一旦我改变了尺寸以便返回一个巨大的尺寸,滚动不再导致图纸的正确居中。为什么一切都在巨大的尺寸上出现故障?我是否需要编写自己的滚动查看器以容纳​​更大量的内容,或者是否有解决方法?

1 个答案:

答案 0 :(得分:1)

所以朋友终于为我解决了这个问题。尽管我正在使用双精度计算,但WPF使用直接x进行绘图。直接x受到浮点数的限制。通过检查维基上浮点数的尾数,我发现我超过了浮点数的尾数,因此该值不再准确。