4 Stimmen

ItemsControl.Items als UIElemente aufzählen

Ich habe eine Liste von Hyperlinks, die über eine ItemsControl in etwa so:

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

Was ich tun muss, ist die Aufzählung der tatsächlichen Hyperlinks im Untermenü, etwa so:

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

Das Problem ist, dass ich nicht scheinen, um einen Weg zu finden, um die tatsächlichen UI-Elemente in der ItemsCollection.Items aufzulisten.

Weiß jemand, wie man das macht oder wie man es umgehen kann?

Ich kann erwähnen, dass ich versuche, ein Menü und Untermenü zu erstellen, das die angeklickten Hyperlinks als eine Art Breadcrumb anzeigt.

U Das Beste wäre, wenn ich irgendwie an das Stackpanel herankäme, denn dieser Code scheint zu funktionieren:

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

8voto

Johan Leino Punkte 3445

Die Lösung sieht folgendermaßen aus:

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

Die Erweiterungsmethode 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;

}

2voto

bendewey Punkte 38830

Versuchen Sie, die ItemContainerGenerator.ContainerFromItem Methode

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

2voto

Hinidu Punkte 31

FindVisualChild aus der Antwort von Johan Leino hat einen Fehler: das Durchlaufen von niedrigeren Ebenen in der Kontrollhierarchie hat keinen Effekt, weil er das Ergebnis des rekursiven Aufrufs nicht überprüft.

Das ist die korrigierte Version.

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

1voto

Andrew Hare Punkte 332190

Versuchen Sie dies:

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

Dies geschieht unter Verwendung der Enumerable.OfType<TResult> Erweiterungsmethode, die die Sammlung auf die Elemente des angegebenen Typs reduziert.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X