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一样。;)
以下是我的操作方法:
<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。