我试图在画布上的椭圆之间绘制一组线 . 我分两步完成:

  • 以下XAML中的第一部分,其中ItemsControl绑定到'SingleCL',使用嵌套的ItemsControl可视化行,绑定到'Points' .

  • 第二部分,绑定相同的集合,可视化椭圆 .

'SingleCL'和'Points'都是ObservableCollection <T>

Point-class有四个属性:VisualHorPos,VisualVerPos,CenterHorPos和CenterVerPos,并实现INotifyPropertyChanged . 属性表示X,Y,其中“Visual”属性被调整为在放置在画布上时表示视图的左上角,因此当使用鼠标移动时,中心位于鼠标指针所在的位置 .

这些点按其各自集合中的Y值进行排序,以便从下到上绘制线条 .

为了避免(隐藏)从0,0到x2绘制的第一行,y2为Point集合中的第一个点,我使用PriorityBinding使其长度为0,因此在实践中隐藏它 .

结果是此图像中显示的红色曲折线
Results

在下面添加点(图像方式) - 首先在集合中 - 仅显示省略号,请参见上图中的蓝点 . 如果我保存数据并从头开始重新加载,则会按预期显示这些行 .

在上面添加点(图像明智) - 在集合中的另一个点之后 - 正确绘制线条,但不更新现有线条以考虑新点 .
More points added

我已经验证了这些点是正确排序的,无论是在添加新点还是在沿Y轴移动时 .

也许我对WPF要求太多了,但是我希望它能够在添加新点时根据ObservableCollection <T>'Points'中项目的顺序从点到点绘制线条,而不仅仅是绑定发生的时间 . 此外,在移动点时,我预计线条会刷新,以便始终根据集合中的顺序从下到上绘制 .

我看到它的方式,问题是一旦创建了线,当对象被移动或添加到集合中时,它们不会反弹 . 有没有办法让ItemsControl重新评估基础ObservableCollection <T>中每个Moved / Added / Removed操作的所有项目?

“绘图代码”

<ItemsControl ItemsSource="{Binding SingleCL}">
                        <ItemsControl.LayoutTransform>
                            <TransformGroup>
                                <ScaleTransform ScaleX="{Binding ElementName=imageZoom, Path=Value}" ScaleY="{Binding ElementName=imageZoom, Path=Value}"/>
                            </TransformGroup>
                        </ItemsControl.LayoutTransform>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <ItemsControl ItemsSource="{Binding Points}">
                                    <ItemsControl.ItemsPanel>
                                        <ItemsPanelTemplate>
                                            <Canvas/>
                                        </ItemsPanelTemplate>
                                    </ItemsControl.ItemsPanel>
                                    <ItemsControl.ItemTemplate>
                                        <DataTemplate>
                                            <Line X2="{Binding CenterHorPos, Mode=OneWay}" Y2="{Binding CenterVerPos, Mode=OneWay}" Stroke="{Binding Color}" StrokeThickness="2">
                                                <!-- Bind X1,Y1 to the previous point, or if not available (as for the first data item) to the same as X2,Y2 -->
                                                <Line.X1>
                                                    <PriorityBinding>
                                                        <Binding Path="CenterHorPos" RelativeSource="{RelativeSource PreviousData}"/>
                                                        <!-- This is the value used of the first binding doesn't work -->
                                                        <Binding Path="CenterHorPos"/>                                                          
                                                    </PriorityBinding>
                                                </Line.X1>
                                                <Line.Y1>
                                                    <PriorityBinding>
                                                        <Binding Path="CenterVerPos" RelativeSource="{RelativeSource PreviousData}"/>
                                                        <!-- This is the value used of the first binding doesn't work -->
                                                        <Binding Path="CenterVerPos"/>                                                          
                                                    </PriorityBinding>
                                                </Line.Y1>
                                            </Line>
                                        </DataTemplate>                                         
                                    </ItemsControl.ItemTemplate>
                                </ItemsControl>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                    <!-- Display markers for all centerlines -->
                    <ItemsControl ItemsSource="{Binding SingleCL}">
                        <ItemsControl.LayoutTransform>
                            <TransformGroup>
                                <ScaleTransform ScaleX="{Binding ElementName=imageZoom, Path=Value}" ScaleY="{Binding ElementName=imageZoom, Path=Value}"/>
                            </TransformGroup>
                        </ItemsControl.LayoutTransform>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <ItemsControl ItemsSource="{Binding Points}">
                                    <ItemsControl.ItemsPanel>
                                        <ItemsPanelTemplate>
                                            <Canvas/>
                                        </ItemsPanelTemplate>
                                    </ItemsControl.ItemsPanel>
                                    <ItemsControl.ItemContainerStyle>
                                        <Style>
                                            <Setter Property="Canvas.Left" Value="{Binding VisualHorPos}" />
                                            <Setter Property="Canvas.Top" Value="{Binding VisualVerPos}" />
                                        </Style>
                                    </ItemsControl.ItemContainerStyle>
                                </ItemsControl>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>

和省略号的代码:

<UserControl x:Class="SMT.View.AutoCalibration.AutoCalibrationMarkerView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300" MouseDown="MarkerMouseDown"
         MouseUp="MarkerMouseUp"
         MouseMove="MarkerMouseMove" Width="10" Height="10"
         Background="Transparent">
<Grid Background="Transparent">
    <Line X1="0" Y1="5" X2="10" Y2="5" Fill="{Binding Color}" Stroke="{Binding Color}" StrokeThickness="0.5"/>
    <Line X1="5" Y1="0" X2="5" Y2="10" Fill="{Binding Color}" Stroke="{Binding Color}" StrokeThickness="0.5"/>
    <Ellipse Width="10" Height="10" Stroke="{Binding Color}" StrokeThickness="0.5" Fill="Transparent"/>
</Grid>

Workaround/Solution

正如@Juan Pablo Garcia Coello在评论中提出的那样,我最终得到了椭圆和线条的不同集合,后者根据需要被清除并重新填充 .