Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF absolute positioning [duplicate]

Tags:

c#

.net

wpf

xaml

Possible Duplicate:
How to bind a canvas to a list of rectangles

A canvas in WPF uses absolute positions correct? I have a sitatution where I have rectangles on a canvas and they are behaving like they are being placed on a vertical stack panel.

I.e. I am placing a rectangle at 0,0, and the next one at 0,0, but it is appearing underneath the first one.

I know for instance that this works as I expected, i.e. the rectangles will overlap as expected,

<Canvas>
    <Rectangle Canvas.Top="50" Canvas.Left="50" Width="50" Height="50"  Fill="AliceBlue" />
    <Rectangle Canvas.Top="60" Canvas.Left="60" Width="50" Height="50"  Fill="Pink" />
</Canvas>

But my situation is a bit more complicated than that,

<Canvas Name="DrawingCanvas" Grid.Column="0" Grid.Row="0" Background="{TemplateBinding Background}" Margin="0,30,0,0">
    <ItemsControl Name="LineContainer" ItemsSource="{Binding Shapes}">
        <ItemsControl.Resources>
            <DataTemplate DataType="{x:Type Models1:Rectangle}">
                <Rectangle Width="30" Height="30" Fill="Aquamarine" Canvas.Left="{Binding X}" Canvas.Top="{Binding Y}" >
                    <Rectangle.LayoutTransform>
                        <RotateTransform Angle="{Binding Angle}"></RotateTransform>
                     </Rectangle.LayoutTransform>
                 </Rectangle>
             </DataTemplate>
         </ItemsControl.Resources>
     </ItemsControl>
 </Canvas>

My code has an items control in it, and it is binding to a list of shapes. These shapes bind to objects like this,

public class Rectangle : IShape, INotifyPropertyChanged
{
    private double angle;

    public string Text { get; set; }
    public double X { get; set; }
    public double Y { get; set; }
    public double Angle {
        get
        {
            return angle;
        }
        set
        {
            if (angle != value)
            {
                angle = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("Angle"));
                }
            }
        }
    }
    public Point Position { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;
}

But all the shapes have the coordinates of 0,0, but they are still lining up one after the other vertically.

Any ideas?

I think I am getting it now though. The items control itself is making it behave like a stack panel. Any alternatives?

like image 676
peter Avatar asked Apr 15 '11 02:04

peter


2 Answers

You are correct that the Canvas uses absolute positioning. In your example, you have specified the top and left positions of each rectangle within the Canvas, but you are missing the Width and Height properties on the Rectangles, which is why they might not be displaying how you want.

The example below shows two overlapping rectangles.

<Canvas>
    <Rectangle Canvas.Top="50" Canvas.Left="50" Width="50" Height="50"  Fill="AliceBlue" />
    <Rectangle Canvas.Top="60" Canvas.Left="60" Width="50" Height="50"  Fill="Pink" />
</Canvas>
like image 74
Andy White Avatar answered Nov 09 '22 15:11

Andy White


Adding the ItemsControl as the only child of the Canvas is not what you want. It should be the panel of the ItemsControl:

<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <Canvas Grid.Column="0" Grid.Row="0" Background="{TemplateBinding Background}" Margin="0,30,0,0">
    </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>

Further the items get wrapped, the attached properties will be ignored if you set them in the DataTemplate, it has to be done like this:

 <ItemsControl.ItemContainerStyle>
     <Style TargetType="{x:Type ContentPresenter}">
         <Setter Property="Canvas.Left" Value="{Binding X}"/>
         <Setter Property="Canvas.Top" Value="{Binding Y}"/>
     </Style>
 </ItemsControl.ItemContainerStyle>
like image 2
H.B. Avatar answered Nov 09 '22 14:11

H.B.