使用Viewbox缩放/拉伸在WPF中维护固定厚度线

我有一个 ,它包含一些垂直和水平 s。 我希望网格可以根据窗口大小进行扩展,并保持其宽高比,因此它包含在

但是,我还希望线条总是以1像素的宽度渲染,所以我使用:

 Line line = new Line(); line.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased); // other line settings here... 

这使得线条的初始外观变得理想,但是一旦开始调整窗口大小,拉伸/缩放就会开始,并且线条再次成为1和2像素厚度的混合。

有没有办法让线条总是1像素厚,还可以调整窗口/网格的大小?

更新 – 根据Clemens的建议使用路径几何

@Clemens – 感谢您突出显示线条和路径之间的渲染差异。 当我尝试使用你的例子重新编写我的代码时,我会感觉到我正在为自己挖掘更多的漏洞,并没有真正掌握整个概念(完全是我的错,不是你的,我只是WPF的新手) 。

我将添加一些截图来说明以下描述:

我正在制作一个游戏板(对于Go的游戏,以防万一有助于理解布局)。 我有一个9×9网格,我打算通过简单地将椭圆添加到特定网格单元来放置游戏块。

然而,为了绘制板上的底线,我需要在板上绘制与单元格中间相交的线(在Go中,块放置在交叉点上,而不是单元格的中间)。

很可能我采取了完全错误的方法,请随时告诉我重新开始不同的路线,而不是在当前结构中进行黑客攻击。

这就是我到目前为止的方式(由于计算坐标的方式,我以编程方式添加路径。不确定是否可以在XAML中完成):

XAML:

                 

C#:

 int cols = 9; int rows = 9; // Draw horizontal lines for (int row = 0; row < rows; row++) { var path = new System.Windows.Shapes.Path(); path.Stroke = Brushes.Black; path.StrokeThickness = 1; path.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased); Grid.SetRow(path, row); Grid.SetColumnSpan(path, cols); Grid.SetZIndex(path, -1); double cellWidth = boardGrid.ColumnDefinitions[0].ActualWidth; double cellHeight = boardGrid.RowDefinitions[0].ActualHeight; double x1 = (cellWidth / 2) / boardGrid.ActualWidth; double y1 = (cellHeight / 2) / boardGrid.ActualHeight; double x2 = ((cellWidth * cols) - (cellWidth / 2)) / boardGrid.ActualWidth; double y2 = (cellHeight / 2) / boardGrid.ActualHeight; path.Data = new LineGeometry(new Point(x1, y1), new Point(x2, y2), (ScaleTransform)boardGrid.TryFindResource("transform")); boardGrid.Children.Add(path); } // Similar loop code follows for vertical lines... 

这是我在使用上面的代码时得到的

使用路径时的结果

这几乎就是我想要的样子。 它为我提出了两个问题:

1)我正在采用正确的方法来计算x1x2y1y2值,方法是将它们乘以总板宽度以创建0到1之间的数字,以便然后可以将ScaleTransform应用于它们?

2)现在我不再使用Viewbox了,如何实现固定比例缩放? 如果我放大窗户,电路板会拉伸不成比例(见下图)。 (它不再对线路进行反锯齿,这很棒。)

拉伸板失去纵横比

我知道这将成为一个单一的post。 我非常感谢你的耐心和回应。

Viewbox只能“直观地”缩放其子元素,包括任何渲染笔划的粗细。 您需要的是仅适用于线条(或其他形状)的几何体的缩放,但不会影响笔划。

您可以通过使用已转换的LineGeometries作为其Data属性的Path对象来绘制线条,而不是使用Line对象。 您可以创建一个ScaleTransform ,它使用Grid的宽度和高度作为x和y方向的缩放因子,从逻辑坐标缩放到视口坐标。 每个LineGeometry(或任何其他几何)将使用0..1范围内的逻辑坐标:

           

为了获得统一的缩放,您可以简单地将ScaleTransform的ScaleXScaleY属性绑定到Grid的ActualWidthActualHeight

     ...  

您还可以从宽度和高度的最小值计算均匀缩放因子,后面还有一些代码:

     ...  

使用像这样的SizeChanged处理程序:

 private void grid_SizeChanged(object sender, SizeChangedEventArgs e) { var transform = grid.Resources["transform"] as ScaleTransform; var minScale = Math.Min(grid.ActualWidth, grid.ActualHeight); transform.ScaleX = minScale; transform.ScaleY = minScale; }