-3

Canvas methods always work when they are in a canvas tag, but When you tryna use them in an itemsControl, they sometimes stop working. here's an example:

<ItemsControl>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Click="Button_Click">Text</Button>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
   
    </ItemsControl>

xaml.cs file

private void Button_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show(Canvas.GetTop(sender as Button).ToString());
    }

Here messagebox returns Nan and I don't know the reason. You can't use SetTop or left method either. Can you help?

Edit: Here's another interesting thing if I give a name to an element it does work, but I don't want that because the names aren't available in the itemTemplate.

here's the code:

 <ItemsControl ItemsSource="{Binding SomeList}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
   <Button x:Name="Btn" Click="Button_Click">Text</Button>
   
    </ItemsControl>

xaml.cs file

 private void Button_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show(Canvas.GetTop(Btn).ToString());
    }
Danial
  • 23
  • 8
  • What do you expect `Canvas.GetTop(sender as Button)` to return when you haven't set the `Canvas.Top` attached property for the `Button`...? – mm8 Jun 27 '23 at 14:07
  • but why the second example works? – Danial Jun 27 '23 at 14:09
  • The Button is not a direct child of the Canvas in the ItemsPanel. Getting or setting any Canvas attached propertiues has no effect. – Clemens Jun 27 '23 at 14:09
  • Yeah, but the second example some how works. I don't know why??!! – Danial Jun 27 '23 at 14:12
  • Works in what way? What is your actual question/issue? – mm8 Jun 27 '23 at 14:12
  • I mentioned two examples. if the you give a name to the button, you can easily use Canvas methods by it's name but when you are binding it, you can't call the names – Danial Jun 27 '23 at 14:15
  • You should use an `ItemContainerStyle` and bind to a property of the data object to define its absolute positon within the `Canvas`. See my answer for an example. – mm8 Jun 27 '23 at 14:16

1 Answers1

1

To position define the absolute position of the element in the ItemTemplate, you should bind the Canvas.Top attached property of the container to a property of the type of objects in the SomeList collection:

<ItemsControl ItemsSource="{Binding SomeList}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="ContentPresenter">
            <Setter Property="Canvas.Top" Value="{Binding Top}" />
        </Style>
    </ItemsControl.ItemContainerStyle>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Click="Button_Click">Text</Button>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

SomeList should be an IEnumerable<T> where the type T has a Top property of type double:

public class Item
{
    public double Top { get; set; }
}
mm8
  • 163,881
  • 10
  • 57
  • 88
  • Yes, but how to update the location. can u send the code if u don't mind? – Danial Jun 27 '23 at 14:22
  • You set the `Top` property to a different value. If you intend to do this dynamically at runtime, the `Item` class should implement `INotifyPropertyChanged` and raise change notifications. – mm8 Jun 27 '23 at 14:22
  • but how to change top property in the view? this is my whole question idea that I couldn't explain well – Danial Jun 27 '23 at 14:49
  • 1
    In the view? ``? – mm8 Jun 28 '23 at 15:13