维持WPF固定厚度的线与Viewbox控件缩放/拉伸(Maintaining fixed-thick

2019-07-21 06:15发布

我有一个<Grid>其中包含一些垂直和水平<Line>秒。 我想网格可缩放与窗口尺寸,并保留其高宽比,因此它包含在<Viewbox Stretch="Uniform">

不过,我也希望总是与1个像素的宽度渲染线,所以我用:

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

这使得线初始外观理想,但只要在开始调整窗口大小,在拉伸/缩放踢,和线成为1首2个像素厚的混合物一次。

有什么办法有行始终为1个像素宽,也允许窗口/格的调整?

更新-使用路径几何按照克莱门斯的建议

@Clemens - 感谢您的高亮线和路径之间的渲染差异。 当我尝试用你的榜样返工我的代码,我收到下沉我正在挖孔多为自己并没有真正把握整个概念的感觉(完全是我的错,不是你的,我只是新的WPF) 。

我会添加一些截图来说明以下说明:

我在做一个游戏板(用于游戏围棋 ,万一有助于理解布局的话)。 我有一个9x9的网格,我打算通过简单地增加一个椭圆特定的网格单元放置棋子。

为了绘制下层线在板上,但是,我需要绘制相交全线单元的中间线(在Go,片被放置在交叉点,该细胞的未中间)。

这很可能是我要带去完全错误的做法,请随时告诉我再次下调了不同的路线出发,而不是目前的结构中黑客左右。

这是我到目前为止已经完成了(我添加的路径编程,由于计算的坐标的方式不知道是否都可以在XAML来完成。):

XAML:

<Grid MinHeight="400" MinWidth="400" ShowGridLines="False" x:Name="boardGrid">
    <Grid.Resources>
        <ScaleTransform x:Key="transform"
            ScaleX="{Binding ActualWidth, ElementName=boardGrid}"
            ScaleY="{Binding ActualHeight, ElementName=boardGrid}" />
    </Grid.Resources>
    <Grid.RowDefinitions>
        <RowDefinition></RowDefinition>
        <!-- more rows, 9 in total -->
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition></ColumnDefinition>
        <!-- more columns, 9 in total -->
    </Grid.ColumnDefinitions>

    <!-- example game pieces -->
    <Ellipse Stroke="Black" Fill="#333333" Grid.Row="3" Grid.Column="2" />
    <Ellipse Stroke="#777777" Fill="#FFFFFF" Grid.Row="4" Grid.Column="4" />
</Grid>

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...

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

这是一个很值得我多么希望它看起来。 它提高了我的2个问题:

1)AM我走在那里我计算正确的方法x1x2y1y2由潜水他们值由总宽度板创建0和1之间的数,使得ScaleTransform然后可以应用于它们?

2)现在,我没有使用Viewbox更多的,我怎么完成的固定比例缩放? 如果我扩大我的窗口,该板延伸出来的比例(见下图)。 (它不抗混叠的线条更多,虽然,这是伟大的。)

我知道这是越来越成为一个位单片职位。 我对你的耐心和反应非常感激。

Answer 1:

视框只能“视觉”扩展其子元素,包括任何呈现中风的厚度。 你需要的是仅适用于线(或其他形状)的几何比例,但保留行程未受影响。

而不是使用的Line对象,你可以画出你的线条由Path使用变换的对象LineGeometries他们的Data属性。 您可以创建一个ScaleTransform从逻辑坐标扩展使用Grid的宽度和高度缩放在x和y方向的因素,视区坐标。 每个LineGeometry(或任何其它几何形状)将在范围0..1使用逻辑坐标

<Grid x:Name="grid">
    <Grid.Resources>
        <ScaleTransform x:Key="transform"
                        ScaleX="{Binding ActualWidth, ElementName=grid}"
                        ScaleY="{Binding ActualHeight, ElementName=grid}"/>
    </Grid.Resources>
    <Path Stroke="Black" StrokeThickness="1">
        <Path.Data>
            <LineGeometry StartPoint="0.1,0.1" EndPoint="0.9,0.9"
                          Transform="{StaticResource transform}"/>
        </Path.Data>
    </Path>
</Grid>

为了得到一个统一的尺度,你可以简单地结合了ScaleTransform的ScaleXScaleY属性要么ActualWidthActualHeight电网:

<Grid x:Name="grid">
    <Grid.Resources>
        <ScaleTransform x:Key="transform"
                        ScaleX="{Binding ActualWidth, ElementName=grid}"
                        ScaleY="{Binding ActualWidth, ElementName=grid}"/>
    </Grid.Resources>
    ...
</Grid>

你还可以从宽度和高度,与位的代码后面的最小值计算出均匀缩放因子:

<Grid x:Name="grid" SizeChanged="grid_SizeChanged">
    <Grid.Resources>
        <ScaleTransform x:Key="transform"/>
    </Grid.Resources>
    ...
</Grid>

与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;
}


文章来源: Maintaining fixed-thickness lines in WPF with Viewbox scaling/stretching