l33t
l33t

Reputation: 19996

Hit testing bound item in ItemsControl?

I have an ItemsControl bound to a list, MyItems, with objects of SomeType. When I click on my UI elements (i.e. ellipses), I want to get hold of the SomeType object.

This does NOT work:

public HitTestResultBehavior SomeTypeHitCallback(HitTestResult result)
{
    if (result.VisualHit is Ellipse)
    {
        var ellipse = result.VisualHit as Ellipse;

        // Does not work...
        object item = itemsSource.ItemContainerGenerator.ItemFromContainer(ellipse);
        // item now equals DependencyProperty.UnsetValue

        // Here I want to change the property of the object
        // associated with the Ellipse...
        var o = item as SomeType;
        o.IsSelected = !o.IsSelected;

        return HitTestResultBehavior.Continue;
    }

    return HitTestResultBehavior.Stop;
}

private void Canvas_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    var pt = e.GetPosition((UIElement)sender);
    VisualTreeHelper.HitTest(
        (UIElement)sender,
        null,
        new HitTestResultCallback(SomeTypeHitCallback),
        new PointHitTestParameters(pt));
}

Here's the XAML:

<ItemsControl x:Name="itemsSource" ItemsSource="{Binding Path=MyItems}">
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <Canvas ClipToBounds="True" PreviewMouseLeftButtonDown="Canvas_PreviewMouseLeftButtonDown" />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Ellipse x:Name="item" Width="{Binding Width}" Height="{Binding Height}" />
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

How can I find the SomeType object?

Upvotes: 0

Views: 1034

Answers (1)

Arsen Mkrtchyan
Arsen Mkrtchyan

Reputation: 50752

itemsSource.ItemContainerGenerator.ItemFromContainer will only work if you pass Item Container, but not visual elements of it. So you need to find ContentPresenter that contains the Ellipse, and pass that as argument to ItemFromContainer method. Since ItemsContainer for ItemsControl is ContentPresenter.

One way I see, is to go up by parents from VisualHit, until you find ContentPresenter, and call ItemFromContainer for that item. Try this, it should work. But the problem here might be that ContentPresenter may exist inside the template of ItemsContainer, and you will get null again. Definitely by chaning ItemsControl to ListBox will make easier to find ListBoxItem, but you will have to re-style it and remove additional features you don't require.

Also try to check Ellipse.DataContext, I could be exactly what you want

Upvotes: 1

Related Questions