WPF absolute positioning

16,275

Solution 1

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>

Solution 2

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>
Share:
16,275
peter
Author by

peter

Business Analyst. Experience with WPF / Winforms / ASP .NET / Silverlight / Design Patterns / OO / Merge Replication.

Updated on June 09, 2022

Comments

  • peter
    peter almost 2 years

    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?

  • peter
    peter about 13 years
    OK, you make a good point there. My situation is a bit more complicated. I'll update my question. You have indeed proved that they will overlap.
  • peter
    peter about 13 years
    Thanks, but that is not working. What is ContentPresenter? Perhaps ContentPresenter needs to be something else.
  • H.B.
    H.B. about 13 years
    Look it up on MSDN. If it won't eat the TargetType, omit it, should work without i think.
  • peter
    peter about 13 years
    This answer you give above does not work. The answer you gave to my other question works.
  • H.B.
    H.B. about 13 years
    Actually, of course it does not work, your setup is completely wrong. Updated the answer.