1

我有一个ItemsControlwith a Canvasas itsItemsPanelPathas the ItemTemplate。目标是绘制图形,因此Path.Data应该包含要在画布中绘制的具有绝对坐标的几何图形。

如果我实例化一个 Canvas 并将路径直接放在其中,它工作正常。

但是如果我使用 ItemsControl,每个 Path 最终都会包裹在 ContentPresenter 中,然后坐标就会丢失,因为 ContentPresenter 与 Canvas 原点对齐。

这是我的代码:

        <ItemsControl
            ItemsSource="{Binding Signals}"
        >
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Path 
                        Stroke="Red"
                        StrokeThickness="1" 
                        StrokeDashCap="Round" 
                        StrokeLineJoin="Round" 
                        Stretch="Fill" 
                        Data={Binding Converter=SignalToGeometryConverter}
                    />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
4

1 回答 1

3

如果你真的需要在那个中使用 a ,Canvas并且真的需要填写父级,那么你可能会遇到困难。如果您可以使用for the ,则一切就绪。ItemsPanelItemsControlGridItemsPanel

让你来到这里的不是ContentPresenter,而是Stretch。这导致Path填充其父级 - 但不是你想的那样。"M 100,100 L 200,200", 与 ,Stretch以外的任何None一个都将从父对象的左上角开始绘制一条线。它将使用的边界框是路径几何实际使用的最大和最小 x 和 y 值。它假设你只关心你费心去的地方。如果您要叠加多个具有不同左上(和右下)边界的路径,它们都将被不同地缩放和偏移,从而形成所有内容的总散列。

当您考虑它时,即使拉伸确实从 0,0 开始,它怎么会知道右下界使用什么?路径彼此不知道。如果你有一个路径,并将你当前的每一个东西作为一个不同的数字添加到其中,那将是一回事。但是这样一来,就没有他们知道的共同参考框架。

所以最快的解决方法是删除Stretch="Fill",但是什么都不会拉伸。只要您使用Canvasfor an ItemsPanel,您最好不要尝试拉伸路径,因为(据我通过测试可以看出)在这种情况下它们无论如何都不会拉伸。

如果您确实想拉伸,首先您需要所有路径都具有相同的边界框,无论它们是否实际使用整个路径。这意味着首先计算您需要多少水平和垂直空间,并在每个路径数据前面加上

M 0,0 M xmax,ymax

...在移动到您想要开始的实际Path点之前。

然后将您的更改CanvasGrid.

这是我测试的代码:

XAML

<Grid>
    <ItemsControl
        ItemsSource="{Binding Signals, RelativeSource={RelativeSource AncestorType=Window}}"
        >
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Grid />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Path 
                    Stroke="DeepSkyBlue" 
                    StrokeThickness="1"
                    Data="{Binding}"
                    Stretch="Fill"
                    />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

C#

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        int left = 10;
        int top = 100;
        int bottom = 200;

        var signals = 
            Enumerable.Range(0, 19)
            .Select(n => $"M 0,0 M 300,300 M {(n * 10) + left},{top} L {(n * 15) + left},{bottom}")
            .ToList();

        //  Show shared bounding box
        signals.Add("M 0,0 L 300,0 L 300,300 L 0,300 Z");

        Signals = signals;
    }

    public IList Signals
    {
        get { return (IList)GetValue(SignalsProperty); }
        set { SetValue(SignalsProperty, value); }
    }

    public static readonly DependencyProperty SignalsProperty =
        DependencyProperty.Register("Signals", typeof(IList), typeof(MainWindow),
            new PropertyMetadata(null));
}
于 2016-10-17T15:53:12.907 回答