【问题标题】:WPF / C#: Connect shapes dynamically with linesWPF / C#:用线条动态连接形状
【发布时间】:2015-07-09 06:47:40
【问题描述】:

我有以下 XAML 代码:

    <Grid>
    <ItemsControl ItemsSource="{Binding Items}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas></Canvas>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Ellipse Width="{Binding Radius}" Height="{Binding Radius}" Fill="{Binding BackColor}" />
                    <Line Stroke="Black" StrokeThickness="1" x:Name="_Line"/>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemContainerStyle>
            <Style>
                <Setter Property="Canvas.Left" Value="{Binding X}"/>
                <Setter Property="Canvas.Top" Value="{Binding Y}"/>
                <Setter Property="Line.X1" Value="{Binding LineX1}"/>
                <Setter Property="Line.X2" Value="{Binding LineX2}"/>
                <Setter Property="Line.Y1" Value="{Binding LineY1}"/>
                <Setter Property="Line.Y2" Value="{Binding LineY2}"/>
            </Style>
        </ItemsControl.ItemContainerStyle>
    </ItemsControl>
</Grid>

这是一个 ItemsControl,它的 ItemPanel 是一个 Canvas,用于动态放置我绑定到的 Obervable 集合中的椭圆。带有 Canvas.Top 和 Canvas.Left 值的椭圆的位置可以正常工作。但它没有画线来连接椭圆。

行的位置在后面的代码中计算正确,我检查了。

【问题讨论】:

    标签: c# .net wpf canvas


    【解决方案1】:

    不应将 Line 属性应用于项目容器。相反,它们应该直接设置在 DataTemplate 中的 Line 控件上:

    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Ellipse Width="{Binding Radius}" Height="{Binding Radius}"
                         Fill="{Binding BackColor}" />
                <Line Stroke="Black" StrokeThickness="1" x:Name="_Line"
                      X1="{Binding LineX1}" Y1="{Binding LineY1}"
                      X2="{Binding LineX2}" Y1="{Binding LineY2}"/>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    

    注意 LineX 和 LineY 属性值是相对于项目位置的。


    编辑:绝对放置所有元素的替代解决方案是不在项目容器上设置 Canvas.Left 和 Canvas.Top 属性(即根本没有 ItemContainerStyle)。

    您可以使用带有 EllipseGeometry 的 Path 而不是 Ellipse,并将 EllipseGeometry 的 Center 属性绑定到 Point 类型的视图模型属性以替代 X 和 Y:

    <ItemsControl ItemsSource="{Binding Items}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Canvas>
                    <Path Fill="{Binding Fill}" Panel.ZIndex="1">
                        <Path.Data>
                            <EllipseGeometry Center="{Binding Center}"
                                             RadiusX="{Binding Radius}"
                                             RadiusY="{Binding Radius}"/>
                        </Path.Data>
                    </Path>
                    <Line Stroke="Black"
                          X1="{Binding LineX1}" Y1="{Binding LineY1}"
                          X2="{Binding LineX2}" Y2="{Binding LineY2}"/>
                </Canvas>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    

    【讨论】:

    • 好的,谢谢,但是现在线条画在错误的位置,椭圆也画在了错误的位置。我会附上一张图片,但我不能:) 编辑:椭圆之间的距离比以前更大,线条有直角但位置错误。 LineX1-X2-Y1-Y2 坐标是正确的。
    • 如前所述 LineX 和 LineY 属性现在是相对于项目的,即 Line.X1 和 Line.Y1 始终为零,而 Line.X2 和 Line.Y2 获取线端点的相对坐标,即分别为 (LineX2 - LineX1) 和 (LineY2 - LineY1) 的差异。此外,要绘制居中的椭圆,您必须将 Ellipse 控件替换为包含 EllipseGeometry 的 Path 控件。
    • 另一种方法是将 Line 控件放在第二个 ItemsControl 的 ItemTemplate 中,它不会在其 ItemContainerStyle 中设置 Canvas.Left 和 Canvas.Top。
    • 谢谢 :D 如果你不介意,再问一个小问题 :) 我不知道如何隐藏椭圆后面的所有线条,所以椭圆总是在顶部。跨度>
    • 在路径上设置Panel.ZIndex="1"。请查看编辑后的答案。
    猜你喜欢
    • 1970-01-01
    • 2014-02-11
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 2014-05-14
    • 2021-03-08
    • 2015-04-27
    • 1970-01-01
    相关资源
    最近更新 更多