C# 将DataTemplate中的控件设置为模板外按钮的CommandTarget

C# 将DataTemplate中的控件设置为模板外按钮的CommandTarget,c#,wpf,C#,Wpf,我正在从事一个项目,涉及在WPF应用程序中从调谐器卡播放电视。最近,我一直在重写电视播放功能,以实现更无缝的交互体验(以前我使用WindowsFormsHost和WinForms控件作为DirectShow渲染目标,导致所有常见的空中空间问题) 该软件同时播放模拟电视和数字电视,由于处理方式不同,我为两者创建了一个播放器和MediaElement(数字电视播放器,数字电视元素,模拟电视播放器,模拟电视元素),从各自的MediaKit类扩展而来 这些控件都在工作,但我现在正在寻找一种方法,使其具有

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

该软件同时播放模拟电视和数字电视,由于处理方式不同,我为两者创建了一个
播放器
MediaElement
数字电视播放器
数字电视元素
模拟电视播放器
模拟电视元素
),从各自的MediaKit类扩展而来

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

我的第一次尝试是使用绑定到所选频道的
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>

虽然这种方法“有效”(电视剧,它自动在模拟和数字之间切换等),但我失去了直接控制电视元素的能力,例如将它们作为命令的目标,例如
MediaCommands.Play
,因为我只引用了
ContentPresenter
或其绑定的
Channel
对象

理想情况下,我希望能够将其中一个
TvPlayer
s设置为
按钮的
CommandTarget
(这可能在
数据模板
之外)。然而,我不知道该怎么做(或者这是否是一个好主意——搜索
DataTemplate
以查找特定控件会让人觉得有点黑客味,而且容易出错)


我觉得我错过了什么,或者走错了方向。有没有人对我如何实现处理频道的通用(最好是声明性)方法有任何建议或建议,同时又不丧失在播放机上执行命令的能力?

您可以尝试使用加载的事件在代码中设置一个字段

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

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

您可以尝试使用加载的事件在代码中设置一个字段

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

当需要的时候,你将有正确的控制,并且不必首先去寻找它们。

谢谢,我没有意识到EvthANDELLS可以被设置在DataTemplates,并且没有考虑加载的事件。我认为这将按要求工作!没问题,很高兴我能帮忙!谢谢,我没有意识到EvthANDLANS可以被派到DataTemplates,也没有考虑加载过的事件。我认为这将按要求工作!没问题,很高兴我能帮忙!