Winrt Hubsection中的引用控件

本文关键字:引用 控件 Hubsection Winrt | 更新日期: 2023-09-27 18:30:10

我想获得对WinRt集线器控件第一部分中MediaElement的引用。有人会认为这是微不足道的,但到目前为止,这是一个完整的PITA。

我在谷歌上搜索了这个问题,发现:

如何访问XAML DataTemplate中的控件?

如何在Windows 8.1商店中访问Hubsection Datatemplate内的任何控件

但是提供的代码不起作用。

我的(相关)Xaml如下:

 <Hub x:Name="MediaHub">
            <Hub.Header>
                <!-- Back button and page title -->
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="80"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <Button  x:Name="backButton" Margin="-1,-1,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
                        Style="{StaticResource NavigationBackButtonNormalStyle}"
                        VerticalAlignment="Top"
                        AutomationProperties.Name="Back"
                        AutomationProperties.AutomationId="BackButton"
                        AutomationProperties.ItemType="Navigation Button"/>
                    <TextBlock x:Name="pageTitle" Text="{StaticResource AppName}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1" 
                        IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Top"/>
                </Grid>
            </Hub.Header>
            <HubSection Width="780" Margin="0,0,80,0">
                <HubSection.Background>
                    <ImageBrush Stretch="UniformToFill" />
                </HubSection.Background>
                <DataTemplate>
                    <Grid Margin="15">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="500"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <MediaElement x:Name="videoElement1" AreTransportControlsEnabled="True"/>
                    </Grid>
                </DataTemplate>
            </HubSection>

下面实现的findname建议返回null:

private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
    this.videoElement = this.MediaHub.Sections[0].FindName("videoElement1") as MediaElement;
    if (this.videoElement != null)
    {
        this.videoElement.MediaOpened += VideoElementMediaOpened;
        this.videoElement.MediaFailed += VideoElementMediaFailed;
        this.videoElement.MarkerReached += VideoElementMarkerReached;
    }
}

VisualTree建议也返回null。

       private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
        {
            this.videoElement = this.FindChildControl<MediaElement>(this, "videoElement1") as MediaElement;
            if (this.videoElement != null)
            {
                this.videoElement.MediaOpened += VideoElementMediaOpened;
                this.videoElement.MediaFailed += VideoElementMediaFailed;
                this.videoElement.MarkerReached += VideoElementMarkerReached;
            }
        }

  private DependencyObject FindChildControl<T>(DependencyObject control, string ctrlName)
        {
            int childNumber = VisualTreeHelper.GetChildrenCount(control);
            for (int i = 0; i < childNumber; i++)
            {
                var child = VisualTreeHelper.GetChild(control, i);
                var fe = child as FrameworkElement;
                // Not a framework element or is null
                if (fe == null) return null;
                if (child is T && fe.Name == ctrlName)
                {
                    // Found the control so return
                    return child;
                }
                else
                {
                    // Not found it - search children
                    DependencyObject nextLevel = FindChildControl<T>(child, ctrlName);
                    if (nextLevel != null)
                        return nextLevel;
                }
            }
            return null;
        }

在这种情况下,可以找到MediaHub,但当使用MediaHub作为"控制"参数递归输入函数FindChildControl时,

int childNumber = VisualTreeHelper.GetChildrenCount(control);

返回count为0,因此返回并向初始调用添加null。尽管如果我设置一个断点,我可以根据Xaml看到HubSections count=4。(定义的章节比我输入的要多,为了简洁起见,省略了)。

经过思考,我似乎被迫使用基于Xaml的风格,更像:

<MediaElement x:Name="videoElement1" AreTransportControlsEnabled="True" 
                                  MediaOpened="VideoElement1_OnMediaOpened"
                                  MediaFailed="VideoElement1_OnMediaFailed"
                                  MarkerReached="VideoElement1_OnMarkerReached"
                                  Source="{Binding SomeViewModelProperty}" />

我在这里的问题是,我经常遇到这样的问题:静默地使用Source= new Uri("xyz")失败,但在同一源文件的代码中使用myMediaElement.SetSource(stream, file.ContentType)="xyz" 100%有效。因此,我想在代码中设置这个源代码,因此需要一个引用。

所以我不想把这个Xaml选项作为我问题的答案,而是想知道如何动态访问给定Hub的HubSection中的控件。在这一点上,我也只是想知道,为了知道。

编辑:

根据Dani的回答,我已经尝试安装WinRt工具包并运行以下代码,但这也返回null。

private void navigationHelper_LoadState(object sender, LoadStateEventArgs e) {
      var m = this.MediaHub.GetDescendantsOfType<MediaElement>().FirstOrDefault();
}

编辑2:

好的,所以基本上这一切都归结为页面生命周期,我还没有读到太多关于它的内容,但需要在Hub的Loaded事件中运行Danis代码和我的原始代码。这样做,所有示例代码块都能工作:

 public HubPage1()
        {
            this.InitializeComponent();
            this.navigationHelper = new NavigationHelper(this);
            this.navigationHelper.LoadState += navigationHelper_LoadState;
            this.MediaHub.Loaded += MediaHub_Loaded;
        }
        void MediaHub_Loaded(object sender, RoutedEventArgs e)
        {
            var m = this.MediaHub.GetDescendantsOfType<MediaElement>().FirstOrDefault();
            this.videoElement =
                this.FindChildControl<MediaElement>(this.MediaHub, "videoElement1") as
                    MediaElement;
        }

这就像WebForms一样。;)

Winrt Hubsection中的引用控件

以下是我的操作方法:

<Hub>
    <HubSection>
        <DataTemplate>
            <Button Loaded="MyButton_OnLoad" />
        </DataTemplate>
    </HubSection>    
</Hub>

然后这个:

private Button _MyButton = default(Button);
private void MyButton_OnLoad(object sender, RoutedEventArgs e)
{
    _MyButton = sender as Button;
}

然后这个:

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    this._MyButton.Visibility = Visibility.Visible;
}

这比浏览VisualTree更好吗?大概它更轻。

祝你好运!

我尝试过使用WinRT XAML Toolkit中的VisualTreeHelperExtensions类。

在那里你可以调用this.MediaHub.GetDescendantsOfType<MediaElement>();,你会得到videoElement1。