2010-02-25 2 views
4

У меня есть список гиперссылок, которые отображаются через ItemsControl, что-то вроде этого:Перечислите ItemsControl.Items в UIElements

<ItemsControl x:Name="SubMenu" Visibility="Collapsed"> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <HyperlinkButton Content="{Binding Name}" 
           NavigateUri="{Binding Url}" 
           TargetName="ContentFrame" 
           Style="{StaticResource LinkStyle}" 
           /> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel Style="{StaticResource LinksStackPanelStyle}" 
          VerticalAlignment="Center" 
          HorizontalAlignment="Left" /> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
    </ItemsControl> 

, что мне нужно сделать, это перечислить фактические гиперссылок в подменю, что-то вроде этого :

foreach (UIElement child in SubMenu.Items) // this does not work! 
    { 
     HyperlinkButton hb = child as HyperlinkButton; 
     if (hb != null && hb.NavigateUri != null) 
     { 
      if (hb.NavigateUri.ToString().Equals(e.Uri.ToString())) 
      { 
       VisualStateManager.GoToState(hb, "ActiveLink", true); 
      } 
      else 
      { 
       VisualStateManager.GoToState(hb, "InactiveLink", true); 
      } 
     } 
    } 

проблема заключается в том, что я не могу показаться, чтобы найти способ, чтобы перечислить фактические элементы пользовательского интерфейса в ItemsCollection.Items.

Кто-нибудь знает, как это сделать или возможное обходное решение?

Я могу упомянуть, что то, что я пытаюсь сделать, - это создать меню и подменю, отображающие гиперссылки, щелкнутые как своего рода сухарики.

UPDATE: Лучше всего было бы, если бы я мог добраться до этого StackPanel как-то, потому что этот код, кажется, работает:

foreach (UIElement child in LinksStackPanel.Children) 
    { 
     HyperlinkButton hb = child as HyperlinkButton; 
     if (hb != null && hb.NavigateUri != null) 
     { 
      if (hb.NavigateUri.ToString().Equals(e.Uri.ToString())) 
      { 
       VisualStateManager.GoToState(hb, "ActiveLink", true); 
      } 
      else 
      { 
       VisualStateManager.GoToState(hb, "InactiveLink", true); 
      } 
     } 
    } 

ответ

8

Решение выглядит следующим образом:

foreach (var item in SubMenu.Items) 
{ 
    var hb = SubMenu.ItemContainerGenerator.ContainerFromItem(item).FindVisualChild<HyperlinkButton>(); 

    if (hb.NavigateUri.ToString().Equals(e.Uri.ToString())) 
    { 
     VisualStateManager.GoToState(hb, "ActiveLink", true); 
    } 
    else 
    { 
     VisualStateManager.GoToState(hb, "InactiveLink", true); 
    } 
} 

Метод расширения FindVisualChild:

public static T FindVisualChild<T>(this DependencyObject instance) where T : DependencyObject 
{ 
    T control = default(T); 

    if (instance != null) 
    { 

     for (int i = 0; i < VisualTreeHelper.GetChildrenCount(instance); i++) 
     { 
      if ((control = VisualTreeHelper.GetChild(instance, i) as T) != null) 
      { 
       break; 
      } 

      control = FindVisualChild<T>(VisualTreeHelper.GetChild(instance, i)); 
     } 
    } 

    return control; 

} 
+0

Это заслуживает большего количества голосов. Только место в сети я нашел решение после поиска в течение дня. –

1

Попробуйте это:

foreach (UIElement child in SubMenu.Items.OfType<UIElement>()) 

Это с помощью Enumerable.OfType<TResult>, который фильтрует коллекцию только для тех элементов, которые имеют указанный тип.

+0

Нет, извините, что не работает. Кажется, что элементы в элементах не являются фактическими элементами пользовательского интерфейса. Элементы содержат typeof (MenuItem), который является бизнес-объектом, который я использую для привязки к коллекции. –

2

Попробуйте использовать метод ItemContainerGenerator.ContainerFromItem

foreach (var item in SubMenu.Items) 
{ 
    var child = SubMenu.ItemContainerGenerator.ContainerFromItem(item); 
    HyperlinkButton hb = child as HyperlinkButton; 
    // use hb 
} 
+0

+1 Ты был прав и помог мне на этом пути. Я решил это по-другому. См. Мой собственный ответ на вопрос. Благодаря! –

2

FindVisualChild от Johan Лейно ответ ошибка: пересекающее более низких уровней в иерархии управления не имеет никакого эффекта потому что он не проверяет результат рекурсивного вызова.

Это фиксированная версия.

public static T FindVisualChild<T>(this DependencyObject instance) where T : DependencyObject 
{ 
    T control = default(T); 

    if (instance != null) 
    { 
     for (int i = 0; i < VisualTreeHelper.GetChildrenCount(instance); i++) 
     { 
      if ((control = VisualTreeHelper.GetChild(instance, i) as T) != null) 
      { 
       break; 
      } 

      if ((control = FindVisualChild<T>(VisualTreeHelper.GetChild(instance, i))) != null) 
      { 
       break; 
      } 
     } 
    } 

    return control; 
} 

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

  • Нет связанных вопросов^_^