4 votes

Obtenir un élément du modèle dans ItemsControl

J'ai un ItemsControl qui est alimenté par une collection observable de certaines classes ViewModel, comme suit :

<ItemsControl ItemsSource="{Binding MyCollection}">
  <ItemsControl.ItemTemplate>
    <DataTemplate Type="{x:Type local:MyViewModel}">
      <Button Content="{Binding ActionName}" Click="ClickHandler"/>
    </DataTemplate>
  <ItemsControl.ItemTemplate>
</ItemsControl>

Cela fonctionne très bien, mais je n'arrive pas à trouver comment faire en sorte que le "ClickHandler" connaisse la classe "MyViewModel" qui est représentée par le modèle de données. Regardez !

private void ClickHandler(object sender, RoutedEventArgs e)
{
  // The 'sender' is the button that raised the event.  Great!
  // Now how do I figure out the class (MyViewModel) instance that goes with this button?
}

9voto

A.R. Points 5329

OK duh, j'ai presque immédiatement réalisé que c'est le 'DataContext' de l'expéditeur. Je vais laisser cette question en suspens, sauf si la communauté pense que cette question est trop évidente.

private void ClickHandler(object sender, RoutedEventArgs e)
{
  // This is the item that you want.  Many assumptions about the types are made, but that is OK.
  MyViewModel model = ((sender as FrameworkElement).DataContext as MyViewModel);
}

4voto

Jon Points 194296

Votre propre réponse fera l'affaire dans ce cas précis. Voici une autre technique qui, bien que beaucoup plus compliquée, fonctionnera également sur n'importe quel scénario, quelle que soit sa complexité :

À partir de sender (qui est un Button ), utilisez VisualTreeHelper.GetParent jusqu'à ce que vous trouviez un ContentPresenter . C'est le type de UIElement que le ItemTemplate que vous avez spécifié est hébergé dans pour chacun de vos articles. Mettons que ContentPresenter dans la variable cp . ( Important : si votre ItemsControl étaient un ListBox alors, au lieu de ContentPresenter nous cherchons un ListBoxItem etc. ).

Ensuite, appelez ItemsControl.ItemContainerGenerator.ItemFromContainer(cp) . Pour ce faire, vous devrez avoir une référence à l'objet spécifique de l'opération. ItemsControl mais cela ne devrait pas être difficile - vous pouvez, par exemple, lui donner une Name et utiliser FrameworkElement.FindName de votre vue elle-même. Le site ItemFromContainer renverra votre ViewModel.

Tout cela, je l'ai appris grâce aux messages stupidement utiles et révélateurs de la part de Dr. WPF .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X