将DataTemplate中的Control设置为模板外部Button的CommandTarget

时间:2010-11-23 04:40:45

标签: c# wpf

我正在开发一个涉及在WPF应用程序中从调谐卡播放电视的项目。最近,我一直在重写电视播放功能,以便与WPF MediaKit一起使用,以实现更加无缝的交互体验(之前我使用WindowsFormsHost和WinForms控件作为DirectShow渲染目标,导致所有常见的播出空间问题)。

该软件同时播放模拟和数字电视,并且处理方式不同,我为PlayerMediaElement创建了DigitalTvPlayerDigitalTvElementAnalogTvPlayerAnalogTvElement),从相应的MediaKit类MediaPlayerBaseMediaElementBase扩展。

这些控件都正常工作,但我现在正在寻找一种方法来拥有一个“电视播放器窗口”,它可以包含一个频道列表(模拟和数字混合)并自动处理它们之间的切换,选择适当的球员。

我第一次尝试这样做涉及使用绑定到所选频道的ContentPresenter和每种频道类型的特定DataTemplate

<Window.Resources>
    <DataTemplate DataType="{x:Type Channels:AnalogChannel}">
        <Controls:AnalogTvGraphFileElement
            AnalogSpecificData="..."
            Channel="{Binding}" />
    </DataTemplate>
    <DataTemplate DataType="{x:Type Channels:DigitalChannel}">
        <Controls:DigitalTvElement
            DigitalSpecificData="..."
            Channel="{Binding}" />
    </DataTemplate>
</Window.Resources>

使用以下窗体:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
    </Grid.ColumnDefinitions>
    <ContentPresenter 
        x:Name="TvPresenter" 
        VerticalAlignment="Stretch" 
        HorizontalAlignment="Center" 
        Content="{Binding ElementName=TvChannels, Path=SelectedItem}" />

    <ListBox Grid.Column="1" x:Name="TvChannels" ItemsSource="{Binding Channels}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

虽然这种方法“有效”(电视播放,它会自动在模拟和数字等之间切换),但我无法直接控制TvElements,例如将它们定位为MediaCommands.Play等命令,我只引用了ContentPresenter或其绑定的Channel对象。

理想情况下,我希望能够将其中一个TvPlayer设置为CommandTarget的{​​{1}}(可能会超出Button) 。但是,我不确定如何做到这一点(或者这是否是一个好主意 - 搜索DataTemplate寻找特定控件时感觉很乱并且容易出错。

我觉得我错过了某些东西,或者以错误的方式解决这个问题。有没有人对如何在不失去在播放器上执行命令的能力的情况下获得通用(最好是声明性的)处理频道的方法有任何建议或建议?

1 个答案:

答案 0 :(得分:1)

您可以尝试使用Loaded事件在代码中设置字段。

<Window.Resources>
    <DataTemplate DataType="{x:Type Channels:AnalogChannel}">
        <Controls:AnalogTvGraphFileElement
            AnalogSpecificData="..." Loaded="OnAnalogTvGraphFileElementLoaded"                Channel="{Binding}" />
    </DataTemplate>
    <DataTemplate DataType="{x:Type Channels:DigitalChannel}">
        <Controls:DigitalTvElement
            DigitalSpecificData="..." Loaded="OnDigitalTvElementLoaded"
            Channel="{Binding}" />
    </DataTemplate>
</Window.Resources>

并且加载的方法将在后面的代码中设置您的字段:

private AnalogTvGraphFileElement analogFileElement;

private void OnAnalogTvGraphFileElementLoaded(object sender, RoutedEventArgs e)
{
    analogFileElement = (AnalogTvGraphFileElement) sender;
}

因此,在需要时,您将拥有正确的控件,而不必先查找它们。