从代码背后访问DataTemplate中的XAML控件?

时间:2012-10-31 20:11:43

标签: c# wpf wpf-controls datatemplate

我有一个我无法在代码隐藏中访问的控件,我相信这是因为它是在DataTempalte中定义的。

整体控件是幻灯片旋转木马。每张幻灯片可以是Image或MediaElement(视频),其内容在ItemSource绑定中定义。转盘位于计时器上,可以从一张幻灯片切换到另一张幻灯片。每次幻灯片更改时,我都会触发一个事件。

当我点击带有视频的幻灯片时,我想停止幻灯片计时器(完成该操作)并启动视频,这是我遇到问题的地方。我无法从代码隐藏中访问MediaPlayer元素Name。我在这一点上的假设是因为它是一个DataTemplate。

这个假设是否正确?如果是这样,我如何从代码隐藏中访问此控件,或者(更重要的是)在幻灯片启动时开始播放?

<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>

2 个答案:

答案 0 :(得分:4)

WPF提供了一种简单直接的方法来访问从DataTemplates生成的命名元素。 MSDN文章How to: Find DataTemplate-Generated Elements中对此进行了解释。

假设您的AutoScrollCarousel派生自ItemsControl,您将获得ContentPresenter,它是这样一个项目的容器:

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

从ContentPresenter中,您将通过FindName方法获取DataTemplate中的命名元素:

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

答案 1 :(得分:2)

我通常建议不要从代码中触摸UIElements ...但MediaElement是一个特殊情况...也许你应该将整个模板包装在一个usercontrol(可能有一些自定义DepProps)中,这样可以让你更好地控制整个过程。

编辑:另一种方法是创建一个带有几个属性的行为(例如IsPlaying)并从那里操纵mediaelement。然后,您可以在DataTemplate的XAML中使用此行为,而无需代码隐藏或用户控件。