tags:

views:

272

answers:

3

I have a list of hyperlinks that are displayed through an ItemsControl, something like this:

 <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>

what I need to do is enumerate the actual hyperlinks in the submenu, something like this:

    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);
            }
        }
    }

The problem is that I can´t seem to find a way to enumerate the actual UI elements in the ItemsCollection.Items.

Anyone know how to do this or a possible workaround?

I can mention that what I´m trying to do is build a menu and submenu that display the hyperlinks clicked as a sort of breadcrumb.

UPDATE: The best thing would be if I could get to that stackpanel somehow because this code seems to work:

    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);
            }
        }
    }
+1  A: 

Try this:

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

This is using the Enumerable.OfType<TResult> extension method that filters the collection down to only those items that are of the specified type.

Andrew Hare
No, sorry that does not work. It seems that elements in Items are not the actual UI elements. Items contains typeof(MenuItem) which is the business object that I use to bind to the collection.
Johan Leino
+1  A: 

Try using the ItemContainerGenerator.ContainerFromItem method

foreach (var item in SubMenu.Items)
{ 
    var child = SubMenu.ItemContainerGenerator.ContainerFromItem(item);
    HyperlinkButton hb = child as HyperlinkButton; 
    // use hb
}
bendewey
+1 You were just about right and helped me along the way. I have solved it a little bit differently. See my own answer to the question. Thanks!
Johan Leino
A: 

The solution looks like this:

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);
            }
        }

The extension method 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;

}
Johan Leino