2014-09-22 2 views
4

XAMLКак получить доступ к TextBlock, который находится внутри DataTemplate (но не привязки) ListBox в XAML?

<ListBox x:Name="lsbQueue" Margin="0,0,0,10" Grid.RowSpan="2" Loaded="lsbQueue_Loaded" SelectionChanged="lsbQueue_SelectionChanged" ItemContainerStyle="{StaticResource ListBoxItemStyle1}" ItemsSource="{Binding}"> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <StackPanel x:Name="stk" Orientation="Vertical"> 
       <!-- This is the bugger which I need to access behind the scenes--> 
       <TextBlock x:Name="tbActive" FontSize="35" FontFamily="Segoe UI Symbol" Text="" Height="115" Margin="0,0,0,-110" Tag="Active"/> 
       <!-- --> 
       <TextBlock Text="{Binding Path=SongName}" FontSize="35" Width="388" FontWeight="Normal" Margin="60,0,0,0"/> 
       <TextBlock Width="390" FontWeight="Thin" Margin="60,-5,0,10" Opacity="0.55"> 
          <Run Text="{Binding Artist}" /> 
          <Run Text=", " /> <!-- space --> 
          <Run Text="{Binding Album}" /> 
       </TextBlock> 
      </StackPanel> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

Выше мой Listbox, который является заселена из кода позади с помощью этого:

C#

void GetQueue() 
{ 
    var songs = new List<song>(); 

    for (int i = 0; i < MediaPlayer.Queue.Count; i++) 
    { 
     songs.Add(new song { 
      SongName = MediaPlayer.Queue[i].Name.ToString(), 
      Album = MediaPlayer.Queue[i].Album.Name.ToString(), 
      Artist = MediaPlayer.Queue[i].Artist.ToString() 
     }); 

    } 
    lsbQueue.ItemsSource = songs.ToList(); 
    //lsbQueue.SelectedValue.ToString(); 
    GlobalVars._song = MediaPlayer.Queue.ActiveSongIndex; 
    lsbQueue.SelectedIndex = GlobalVars._song; 
    // ....... 
} 

и

public class song 
{ 
    public string SongName { get; set; } 
    public string Album { get; set; } 
    public string Artist { get; set; } 
} 

public class Song : List<song> 
{ 
    public Song() 
    { 
     Add(new song { 
      SongName = "", 
      Album = "", 
      Artist = "" 
     }); 
    } 
} 

Я попытался с помощью VisualTreeHelper и другие методы расширения, которые можно найти здесь:

GeekChamp

Falafel Blog

Но я не имел никакого успеха. Я почти отказался от этого. У кого-нибудь есть идеи, что можно сделать. Спасибо.

enter image description here

Как вы можете видеть - я могу успешно получить очереди СМИ, но я хотел бы показать визуальную подсказку на левой стороне «SelectedItem», как игровой персонаж в TextBlock - tbActive. Надеюсь это поможет!

+0

Вам необходимо следовать руководству GeekChamp на письмо. См. Решение. –

+0

Привет. Извините Если я не смог сообщить вам, что мне нужно. Фактически, я смог успешно получить медиа-очередь (песни, находящиеся в очереди в очереди). Но я хотел бы показать теперь играющий символ - рядом с «Активной песней», а 'tbActive' именно это! Я с нетерпением ожидал получить доступ к tbActive в надежде изменить его свойство «Text», но только из «SelectedItem» или «SelectedIndex». Спасибо. – CriticalError

+0

Да, решение с моим именем на нем делает именно то, что вы хотите. :) –

ответ

1

Поскольку <TextBlock> - это первая запись в DataTemplate, к которой вы пытаетесь получить доступ, используйте предоставленную функцию из учебника GeekChamp.

<ListBox x:Name="lb" SelectionChanged="lb_SelectionChanged"/> 

// namespaces 
using System.Windows.Media; 

private T FindFirstElementInVisualTree<T>(DependencyObject parentElement) where T : DependencyObject 
{ 
    var count = VisualTreeHelper.GetChildrenCount(parentElement); 
    if (count == 0) 
     return null; 

    for (int i = 0; i < count; i++) 
    { 
     var child = VisualTreeHelper.GetChild(parentElement, i); 

     if (child != null && child is T) 
     { 
      return (T)child; 
     } 
     else 
     { 
      var result = FindFirstElementInVisualTree<T>(child); 
      if (result != null) 
       return result; 
     } 
    } 
    return null; 
} 

private void lb_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    // get the ListBoxItem by SelectedIndex OR index number 
    //ListBoxItem lbi = (ListBoxItem) this.lb.ItemContainerGenerator.ContainerFromIndex(lb.SelectedIndex); 

    // get the ListBoxItem by SelectedItem or object in your ViewModel 
    ListBoxItem lbi = (ListBoxItem)this.lb.ItemContainerGenerator.ContainerFromItem(lb.SelectedItem); 

    // get your textbox that you want 
    TextBlock tbActive= FindFirstElementInVisualTree<TextBlock>(lbi); 
} 
+0

:(Это не сработало. Я установил точку останова, а 'lbi' равно null, и поэтому даже TextBlock имеет значение null :( – CriticalError

+0

И какое число является выбранным индексом?Также, если вы используете выбранный элемент, что он равен точке останова? –

+0

Выбранный указатель - это исполняемая в настоящее время песня, которую я получаю от 'MediaPlayer.Queue.ActiveSongIndex'. Пожалуйста, взгляните на изображение, которое я только что добавил в мой вопрос. Благодарю. – CriticalError

0

Вы можете попробовать получить StackPanel из выбранного элемента ListBox с помощью оператора as, а затем использовать свойство Children с индексом, чтобы добраться до вашего TextBlock.

StackPanel temp = lsbQueue.SelectedItem as StackPanel; 
var textBlock = temp.Children[0] as TextBlock; 

Что именно вы хотите достичь? Возможно, другой способ привязки + возможный ValueConverter был бы лучшим решением ...

+0

Довольно уверен, что 'lsbQueue.SelectedItem' будет' song', а не Control. Таким образом, это приведет к ошибке, так как temp будет «null». –

1

выше ответ будет сгенерировано исключение - так же, как Chubosaurus Software предложил SelectedItem будет 'Песня' и thefore TextBlock будет также null. И это не сработает.

Смежные вопросы