我正在开发一个涉及在WPF应用程序中从调谐卡播放电视的项目。最近,我一直在重写电视播放功能,以便与WPF MediaKit一起使用,以实现更加无缝的交互体验(之前我使用WindowsFormsHost和WinForms控件作为DirectShow渲染目标,导致所有常见的播出空间问题)。
该软件同时播放模拟和数字电视,并且处理方式不同,我为Player
,MediaElement
创建了DigitalTvPlayer
和DigitalTvElement
, AnalogTvPlayer
,AnalogTvElement
),从相应的MediaKit类MediaPlayerBase和MediaElementBase扩展。
这些控件都正常工作,但我现在正在寻找一种方法来拥有一个“电视播放器窗口”,它可以包含一个频道列表(模拟和数字混合)并自动处理它们之间的切换,选择适当的球员。
我第一次尝试这样做涉及使用绑定到所选频道的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
寻找特定控件时感觉很乱并且容易出错。
我觉得我错过了某些东西,或者以错误的方式解决这个问题。有没有人对如何在不失去在播放器上执行命令的能力的情况下获得通用(最好是声明性的)处理频道的方法有任何建议或建议?
答案 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;
}
因此,在需要时,您将拥有正确的控件,而不必先查找它们。