Emanuele
Emanuele

Reputation: 56

How to get the absolute screen coordinates of an element placed inside a DataTemplate

I have a ListView that uses a UserControl as DataTemplate:

<ListView>
    <ListView.ItemTemplate>
        <DataTemplate>
            <views:TaskerInfoView />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

I need the absolute screen coordinates of a Button placed inside the TaskerInfoView usercontrol.

I tried with this code:

var newButtonPoint = button.PointToScreen(new Point(0, 0));

but I received the exception "This Visual is not connected to a PresentationSource" I suppose because the button is inside a DataTemplate so it's not connected to a visual element.

UPDATE I've found why I had received that exception: before the PointToScreen call I move the item inside the ObersvableCollection, that is the ItemsSource of the ListView:

this._taskList.Move(currentIndex, currentIndex - 1);  // _taskList is the ObservableCollection<>
var newButtonPoint = button.PointToScreen(new Point(0, 0));

If I remove the ObservableCollection<>.Move, the PointToScreen works correctly.

I think that internally the ObservableCollection<>.Move removes the item and inserts another one in the new position. The exception is raised because button contains a reference to the removed element that is actually disconnected from the TreeVisual

Upvotes: 1

Views: 726

Answers (1)

eran otzap
eran otzap

Reputation: 12533

For example :

xaml :

    <ListBox x:Name="myListBox" SelectedIndex="2">
        <ListBoxItem>1</ListBoxItem>
        <ListBoxItem>2</ListBoxItem>
        <ListBoxItem>3</ListBoxItem>
        <ListBoxItem>4</ListBoxItem>
        <ListBoxItem>5</ListBoxItem>
    </ListBox>

    <Button Content="GetIndexFromContainer" Click="Button_Click" />

cs :

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var index = GetSelectedIndexFromList();
    }

    private int GetSelectedIndexFromList()
    {
        var container = myListBox.ItemContainerGenerator.ContainerFromItem(MyListBox.SelectedItem);
        var index = myListBox.ItemContainerGenerator.IndexFromContainer(container);
        return index;
    }

Upvotes: 1

Related Questions