Я хочу получить ссылку на MediaElement, который находится в первом разделе управления концентратором WinRt. Казалось бы, это было бы тривиально, но до сих пор это была полная ПИТА.
У меня проблема с Google и нашел:
Как получить доступ к элементу управления внутри XAML 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 обнаружен, но когда функция FindChildControl рекурсивно вводится с использованием MediaHub в качестве параметра "control",
int childNumber = VisualTreeHelper.GetChildrenCount(control);
возвращает значение 0 и, таким образом, возвращается и пузырится до нуля до начального вызова. Хотя, если я установил точку прерывания, я могу увидеть счет HubSections count=4
в соответствии с Xaml. (Определено больше разделов, чем то, что я ввел, опущено для краткости).
Поразмыслив, кажется, что я вынужден использовать стиль на основе 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 рассматривался как ответ на мой вопрос, а скорее как динамически получать доступ к элементу управления в HubSection данного концентратора. В этот момент я просто хотел бы знать ради знания.
Редактировать:
В соответствии с ответом Dani я попытался установить WinKit toolkit и запустить следующий код, но это также возвращает null.
private void navigationHelper_LoadState(object sender, LoadStateEventArgs e) {
var m = this.MediaHub.GetDescendantsOfType<MediaElement>().FirstOrDefault();
}
Изменить 2:
Хорошо, так что в основном все сводится к жизненному циклу страницы, о котором я еще не много читал, но при этом работает как код Danis, так и исходный код в событии Loaded концентратора. Сделайте это и все примеры блоков кода:
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? Может быть. Это легче.
Удачи!
Я пробовал с классом VisualTreeHelperExtensions
из WinRT XAML Toolkit.
Там вы можете вызвать this.MediaHub.GetDescendantsOfType<MediaElement>();
и вы получите videoElement1.
Button Loaded
в вашем XAML. Это, конечно, не требует добавления всего раздутого инструментария в ваше приложение или обхода визуального дерева. Кроме извлеченияScrollViewers
из элементов управления списком или отладки пользовательского интерфейса - я не думаю, что обычно касаюсь визуального дерева где-либо еще.