Справочный контроль в Winrt Hubsection

1

Я хочу получить ссылку на MediaElement, который находится в первом разделе управления концентратором WinRt. Казалось бы, это было бы тривиально, но до сих пор это была полная ПИТА.

У меня проблема с Google и нашел:

Как получить доступ к элементу управления внутри XAML DataTemplate?

Как получить доступ к любому элементу управления внутри Hubsection Datatemplate в хранилище Windows 8.1

Но предоставленный код не работает.

Мой (соответствующий) 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 снова и снова. ;)

Теги:
winrt-xaml
windows-8.1

2 ответа

3
Лучший ответ

Вот как я это делаю:

<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? Может быть. Это легче.

Удачи!

  • 0
    Я думаю, что вы хотели напечатать Button Loaded в вашем XAML. Это, конечно, не требует добавления всего раздутого инструментария в ваше приложение или обхода визуального дерева. Кроме извлечения ScrollViewers из элементов управления списком или отладки пользовательского интерфейса - я не думаю, что обычно касаюсь визуального дерева где-либо еще.
  • 0
    Да, это намного лучше. Пенни начал падать на многие вещи сейчас. Спасибо.
Показать ещё 4 комментария
2

Я пробовал с классом VisualTreeHelperExtensions из WinRT XAML Toolkit.

Там вы можете вызвать this.MediaHub.GetDescendantsOfType<MediaElement>(); и вы получите videoElement1.

  • 0
    Спасибо, что я установил и попробовал это, и я все еще получаю ноль. Можете ли вы посоветовать, какое событие вы используете для вызова этого кода? Пожалуйста, смотрите мое обновление. Я использую событие LoadState.
  • 0
    Неважно - отсортировано.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню