ItemsControl仅显示每个对象的第一个Item

时间:2018-03-01 14:36:41

标签: c# .net wpf data-binding

我在将一组线条绘制到画布中时遇到问题。谷歌向我展示了几个来源,但我无法找到真正的解决方案。我希望你们有一个暗示我。

我的结构如下:

String inputLine;
            StringBuilder response = new StringBuilder();

            while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);       
    }
            in.close();

XAML:

public class CanvasLine
{
    public Double X1 { get; set; }
    public Double X2 { get; set; }
    public Double Y1 { get; set; }
    public Double Y2 { get; set; }
    public Brush StrokeColor { get; set; }
    public Double StrokeThickness { get; set; }
    public DoubleCollection StrokeDashArray { get; set; }
}

public class CanvasObject
{
    public String Name { get; set; }
    public ObservableCollection<CanvasLine> CanvasLines { get; set; }
}

public class ViewModel
{
    ...
    public ObservableCollection<CanvasObject> CanvasObjects;
    ...
}

这是为了演示,我可能删除了太多。

我的问题是画布中只显示每个<Window x:Class="XXX.Views.MainWindow" xmlns:vm="clr-namespace:XXX.Viewmodels" xmlns:converter="clr-namespace:XXX.Converter" Title="XXX" Height="480" Width="640"> <Window.DataContext> <vm:ViewModel/> </Window.DataContext> <Grid> <ItemsControl Grid.Column="1" Grid.Row="2" Margin="0" ItemsSource="{Binding CanvasObjects, UpdateSourceTrigger=PropertyChanged}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <Canvas/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <Line DataContext="{Binding CanvasLines}" Stroke="{Binding StrokeColor}" StrokeDashArray="{Binding StrokeDashArray}" StrokeThickness="{Binding StrokeThickness}"> <Line.X1> <MultiBinding Converter="{StaticResource MultiplicationConverter}"> <Binding Path="X1"/> <Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=Canvas}"/> </MultiBinding> </Line.X1> <Line.X2> <MultiBinding Converter="{StaticResource MultiplicationConverter}"> <Binding Path="X2"/> <Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=Canvas}"/> </MultiBinding> </Line.X2> <Line.Y1> <MultiBinding Converter="{StaticResource MultiplicationConverter}"> <Binding Path="Y1"/> <Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=Canvas}"/> </MultiBinding> </Line.Y1> <Line.Y2> <MultiBinding Converter="{StaticResource MultiplicationConverter}"> <Binding Path="Y2"/> <Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=Canvas}"/> </MultiBinding> </Line.Y2> </Line> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </Grid> 的第一个CanvasLine。如果我放弃CanvasObjectCanvasObject并将DataContext="{Binding CanvasLines}"直接绑定到ItemsControl,它会正常工作,但在接下来的步骤中我需要添加更多对象以及i&i #39;我试图避免使用大量的行来保持某种对象结构。

由于我对这个MVVM Binding的东西很陌生,我对你想分享的任何想法感到高兴。

问候。

1 个答案:

答案 0 :(得分:1)

您不得在DataTemplate中绑定Line的DataContext。它确实已经包含对相应集合元素的引用。

实际需要的是嵌套的ItemsControls,一个用于CanvasObjects集合的外部,以及一个用于CanvasLines的内部:

<ItemsControl ItemsSource="{Binding CanvasObjects}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ItemsControl ItemsSource="{Binding CanvasLines}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Line Stroke="{Binding StrokeColor}"
                              StrokeDashArray="{Binding StrokeDashArray}"
                              StrokeThickness="{Binding StrokeThickness}">
                            ...
                        </Line>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

由于您显然是以相对坐标绘制线条,因此我建议您进行以下更改。而不是X1,Y1,X2,Y2让CanvasLine有两个点,P1和P2:

public class CanvasLine
{
    public Point P1 { get; set; }
    public Point P2 { get; set; }
    public Brush Stroke { get; set; }
    public double StrokeThickness { get; set; }
    public DoubleCollection StrokeDashArray { get; set; }
}

现在让你的XAML使用带有LineGeometry而不是Line的Path。然后将Transform属性分配给外部ItemsControl资源中的相应ScaleTransform:

<ItemsControl ItemsSource="{Binding CanvasObjects}">
    <ItemsControl.Resources>
        <ScaleTransform x:Key="lineTransform"
            ScaleX="{Binding ActualWidth,
                     RelativeSource={RelativeSource AncestorType=ItemsControl}}"
            ScaleY="{Binding ActualHeight,
                     RelativeSource={RelativeSource AncestorType=ItemsControl}}"/>
    </ItemsControl.Resources>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ItemsControl ItemsSource="{Binding CanvasLines}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Path Stroke="{Binding Stroke}"
                              StrokeDashArray="{Binding StrokeDashArray}"
                              StrokeThickness="{Binding StrokeThickness}">
                            <Path.Data>
                                <LineGeometry
                                    Transform="{StaticResource lineTransform}"
                                    StartPoint="{Binding P1}"
                                    EndPoint="{Binding P2}"/>
                            </Path.Data>
                        </Path>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>