C# 从CodeBehind访问DataTemplate中的XAML控件?

C# 从CodeBehind访问DataTemplate中的XAML控件?,c#,wpf,wpf-controls,datatemplate,C#,Wpf,Wpf Controls,Datatemplate,我有一个无法在codebehind中访问的控件,我相信这是因为它是在DataTempalte中定义的 整个控件是一个幻灯片放映转盘。每张幻灯片可以是图像或MediaElement(视频),其内容在ItemSource绑定中定义。旋转木马有一个定时器,可以从一张幻灯片切换到下一张幻灯片。每次幻灯片更改时,我都会触发一个事件 当我用视频点击幻灯片时,我想停止幻灯片计时器(这样做)并启动视频,这就是我遇到问题的地方。我无法从我的codebehind访问MediaPlayer元素Name。我在这一点上的

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

整个控件是一个幻灯片放映转盘。每张幻灯片可以是图像或MediaElement(视频),其内容在ItemSource绑定中定义。旋转木马有一个定时器,可以从一张幻灯片切换到下一张幻灯片。每次幻灯片更改时,我都会触发一个事件

当我用视频点击幻灯片时,我想停止幻灯片计时器(这样做)并启动视频,这就是我遇到问题的地方。我无法从我的codebehind访问
MediaPlayer
元素
Name
。我在这一点上的假设是因为它是一个数据模板

这个假设正确吗?如果是这样,我如何从codebehind访问此控件,或者(更确切地说)在幻灯片出现时让它开始播放

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

...

我通常建议不要触摸代码中的UIElements。。。但是MediaElement是一个特例。。。也许你应该将整个模板包装在一个usercontrol中(也许使用一些定制的DepProps),这样你就可以更好地控制整个模板


编辑:另一种方法是使用几个属性(比如isplay)创建一个行为,并从中操作mediaelement。然后,您可以在DataTemplate的XAML中使用此行为,而不需要代码隐藏或用户控件。

WPF提供了一种简单而直接的方法来访问从DataTemplates生成的命名元素。MSDN文章对此进行了解释

假设您的AutoScrollCarousel是从ItemsControl派生的,您将获得ContentPresenter,它是一个项目的容器,如下所示:

AutoScrollCarousel carousel = ...
object item = ...
var contentPresenter =
    carousel.ItemContainerGenerator.ContainerFromItem(item) as ContentPresenter;
从ContentPresenter,您可以通过以下方法获得DataTemplate中的命名元素:


但这不是仍然在数据模板中吗?我不知道在哪里我可以将模板分离成UserControl,这仍然不会导致我需要控制DataTemplate中的某些内容。由于我的ItemsPanel/ItemsTemplate绑定到一个模型,我没有看到我可以标记(我还没有)什么DependencyProperties来触发它。是的,你仍然可以在DataTemplate中拥有你的UserControl,但是UserControl本身就有代码,你也可以声明一些DependencyProperties,比如bool IsPlaying,在changedcallback中,mediaelement.play()或stop()可以理解这一部分,但是如何翻转
isplay
标志呢?我认为在这种情况下,这个问题合并成一个有约束力的问题。DataTemplate只知道数据模型。我不需要在DataTemplate之外获取一个值来查看幻灯片是否可见吗?好问题。。。如果您已经成功地从代码隐藏中获取了对MediaElement的引用,那么您打算怎么做呢?从代码隐藏中,我正要运行
Play()
。但是使用幻灯片放映设置,我需要将
IsPlaying
(如您所建议)绑定到祖先的
IsSelected
属性,因为
datatemplay
只能访问数据模型。
var dataTemplate = contentPresenter.ContentTemplate;
var mediaPlayer = dataTemplate.FindName("MediaPlayer", contentPresenter) as MediaElement;