ItemsControl仅显示每个对象的第一个Item [英] ItemsControl only shows first Item of each object

查看:51
本文介绍了ItemsControl仅显示每个对象的第一个Item的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在将线的集合绘制到画布中时遇到问题.Google向我展示了一些消息来源,但是我找不到真正的解决方案.我希望你们对我有个提示.

I have a problem plotting a collection of lines into a canvas. Google showed me several sources but i couldn't find a real solution for this one. I hope you guys have a hint for me.

我的结构如下:

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

XAML:

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

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

This is for demonstration, i might have deleted too much.

我的问题是在画布中仅显示每个 CanvasObject 的第一个 CanvasLine .如果我放弃 CanvasObject DataContext ="{Binding CanvasLines}" 并将直接将 ItemsControl 绑定到ObservableCollection< CanvasLine> ,但是在接下来的步骤中,我需要添加更多对象,并且我试图避免使用太多的行来保持某种对象结构.

My problem is that only the first CanvasLine for each CanvasObject is shown in the canvas. It works fine if i give up the CanvasObject and the DataContext="{Binding CanvasLines}" and directly bind the ItemsControl to a ObservableCollection<CanvasLine> but in the next steps i need to add more objects and also i'm trying to avoid a huge list of lines an to keep some kind of object structure.

由于我对MVVM绑定这个东西还很陌生,所以我很高兴分享您的想法.

Since i'm pretty new to this MVVM Binding stuff i'm happy about any thoughts you like to share.

问候.

推荐答案

您不得在DataTemplate内绑定行的 DataContext .它已经包含了对适当的collection元素的引用.

You must not bind a Line's DataContext inside the DataTemplate. It does already hold a reference to the appropriate collection element.

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

What you actually need are nested ItemsControls, an outer one for the CanvasObjects collection, and an inner one for 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:


Since you are apparently drawing your lines in relative coordinates, I'd like to suggest the following changes. Instead of X1, Y1, X2, Y2 let yout CanvasLine have two Points, P1 and 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的Path而不是Line.然后将Transform属性分配给外部ItemsControl的资源中的适当ScaleTransform:

Now make your XAML use a Path with a LineGeometry instead of a Line. Then assign the Transform property to an appropriate ScaleTransform in the outer ItemsControl's resources:

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

这篇关于ItemsControl仅显示每个对象的第一个Item的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆