2012-10-31 3 views
1

J'ai un contrôle que je suis incapable d'accéder dans le codebehind, et je crois que c'est parce qu'il est défini dans un DataTempalte.Accédez au contrôle XAML dans DataTemplate à partir de CodeBehind?

Le contrôle global est un carrousel de diaporama. Chaque diapositive peut être une Image ou un MediaElement (vidéo) dont le contenu est défini dans une liaison ItemSource. Le carrousel est sur une minuterie pour passer d'une diapositive à l'autre. Chaque fois que la diapositive change, je déclenche un événement à cet effet.

Quand je frappe une diapositive avec une vidéo que je voudrais arrêter le chronomètre de glissement (fait que) et lancer la vidéo, ce qui est là où j'ai rencontré un problème. Je ne peux pas accéder à l'élément MediaPlayerName à partir de mon codebehind. Mon hypothèse à ce stade est parce que c'est un DataTemplate.

Cette hypothèse est-elle correcte? Si c'est le cas, comment puis-je avoir accès à ce contrôle depuis le codebehind, ou (plus précisément) est-ce qu'il commence à jouer quand la diapositive apparaît?

<ctrl:AutoScrollCarousel ...> 
    <ctrl:AutoScrollCarousel.ItemsPanel> 
     <ItemsPanelTemplate> 
      <StackPanel Orientation="Horizontal" /> 
     </ItemsPanelTemplate> 
    </ctrl:AutoScrollCarousel.ItemsPanel> 
    <ctrl:AutoScrollCarousel.ItemTemplate> 
     <DataTemplate> 
      <Border x:Name="Border" VerticalAlignment="Center" 
        Width="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type UserControl},Mode=FindAncestor}}"> 
       <Grid Background="White"> 
        ... 
        <Image Source="{Binding ContentImage}" Grid.Row="1" Grid.Column="1" Stretch="UniformToFill" 
          HorizontalAlignment="Center" 
          Visibility="{Binding ContentImage, Converter={StaticResource VisibilityConverter}}" /> 

        <MediaElement Name="MediaPlayer" Source="{Binding ContentVideo}" Grid.Row="1" Grid.Column="1" Stretch="UniformToFill" LoadedBehavior="Play" 
            Visibility="{Binding ContentVideo, Converter={StaticResource VisibilityConverter}}" MediaEnded="MediaPlayer_MediaEnded" /> 

        <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Title}" Foreground="Black" 
           FontFamily="Segoe UI" FontWeight="Light" HorizontalAlignment="Left" FontSize="75" Margin="0" VerticalAlignment="Center" /> 

        <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding ContentHeadline}" Foreground="Black" 
           FontFamily="Segoe UI" FontWeight="Light" HorizontalAlignment="Left" FontSize="50" VerticalAlignment="Center" 
           TextWrapping="Wrap"> 
        </TextBlock> 
       </Grid> 
      </Border> 
     </DataTemplate> 
    </ctrl:AutoScrollCarousel.ItemTemplate> 
</ctrl:AutoScrollCarousel> 

Répondre

2

Je recommande normalement de ne pas toucher UIElements de code ... mais le MediaElement est un cas particulier ... peut-être vous devriez envelopper le modèle tout dans un usercontrol (peut-être avec quelques DepProps personnalisés) et qui vous donner un meilleur contrôle sur l'ensemble.

Edit: Une autre approche serait de créer un comportement avec un couple de propriétés (par exemple isPlaying) et de manipuler le MediaElement à partir de là. Vous pouvez ensuite utiliser ce comportement dans le code XAML du DataTemplate, sans avoir besoin de code derrière ou usercontrols.

+0

Mais ce ne serait pas encore à l'intérieur du DataTemplate? Je ne vois pas où je séparerais le modèle dans un UserControl, cela ne me donnerait pas le besoin de contrôler quelque chose qui se trouve dans un DataTemplate. Puisque mes ItemsPanel/ItemsTemplate sont liés à un modèle, je ne vois pas ce que DependancyProperties je pourrais signaler (que je ne suis pas déjà) pour le déclencher. –

+1

Eh oui, vous auriez encore votre UserControl dans le DataTemplate, mais ont UserControls code derrière par eux-mêmes, et vous pouvez également déclarer certaines propriétés de dépendance comme bool isPlaying, et dans le changedcallback pour ce faire la mediaelement.play() ou arrêter() et ainsi de suite –

+0

Je comprends cette partie, mais comment pourrais-je inverser le drapeau 'IsPlaying'? Je pense que dans ce cas la question fusionne à une question contraignante. DataTemplate connaît uniquement le modèle de données. N'aurais-je pas besoin de récupérer une valeur en dehors du DataTemplate pour voir si la diapositive est visible ou non? –

2

WPF offre un moyen simple et facile d'accéder aux éléments nommés qui sont générés à partir DataTemplates. Il est expliqué dans l'article MSDN How to: Find DataTemplate-Generated Elements.

Supposé que votre AutoScrollCarousel est dérivé de ItemsControl, vous obtiendrez le ContentPresenter qui est le conteneur d'un élément comme celui-ci:

AutoScrollCarousel carousel = ... 
object item = ... 
var contentPresenter = 
    carousel.ItemContainerGenerator.ContainerFromItem(item) as ContentPresenter; 

De l'ContentPresenter vous obtiendrez l'élément nommé dans le DataTemplate au moyen de la méthode FindName:

var dataTemplate = contentPresenter.ContentTemplate; 
var mediaPlayer = dataTemplate.FindName("MediaPlayer", contentPresenter) as MediaElement; 
Questions connexes