Search code examples
c#.netwpfpixelsense

How to iterate over the elements in a LibraryStack?


I have the following definition of a LibraryStack:

<s:LibraryStack Name="TaggingContainer" Margin="20" Grid.Row="1" Grid.ColumnSpan="2" AllowDrop="True" Height="300" Width="300" s:SurfaceDragDrop.DragLeave="TaggingContainer_DragLeave" s:SurfaceDragDrop.DragEnter="TaggingContainer_DragEnter" s:SurfaceDragDrop.PreviewDrop="LibraryStack_PreviewDrop">
            <s:LibraryStack.ItemTemplate>
                <DataTemplate>
                    <Label Content="{Binding Name}" Tag="{Binding}" FontSize="20" Margin="10,10,10,10" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" Background="#c49b14" BorderBrush="White" BorderThickness="2" s:Contacts.PreviewContactDown="Label_PreviewContactDown"></Label>
                </DataTemplate>
            </s:LibraryStack.ItemTemplate>
        </s:LibraryStack>

Now in the code-behind I want to iterate over all the labels that are contained in the LibraryStack (the label defined in the data template).

But if I use

foreach (FrameworkElement element in TaggingContainer.Items) {
}

I iterate over the data objects that are in the TaggingContainer and not the Datatemplates. How can I change that?


Solution

  • The easiest way is probably to find every LibraryStackItem or Label under the LibraryStack in the Visual Tree. Try this

    private void SomeMethod()
    {
        // Get All Labels
        List<Label> labels = GetVisualChildCollection<Label>(TaggingContainer);
        foreach (Label label in labels)
        {
            //...
        }
    }
    

    Alternatively you could get the container for each element and get the Label that way instead

    foreach (var element in TaggingContainer.Items)
    {
        LibraryStackItem libraryStackItem = TaggingContainer.ItemContainerGenerator.ContainerFromItem(element) as LibraryStackItem;
        Label label = VisualTreeHelpers.GetVisualChild<Label>(libraryStackItem);
    }
    

    GetVisualChild

    private static T GetVisualChild<T>(DependencyObject parent) where T : Visual
    {
        T child = default(T);
    
        int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < numVisuals; i++)
        {
            Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
            child = v as T;
            if (child == null)
            {
                child = GetVisualChild<T>(v);
            }
            if (child != null)
            {
                break;
            }
        }
        return child;
    }
    

    GetVisualChildCollection

    public static List<T> GetVisualChildCollection<T>(object parent) where T : Visual
    {
        List<T> visualCollection = new List<T>();
        GetVisualChildCollection(parent as DependencyObject, visualCollection);
        return visualCollection;
    }
    private static void GetVisualChildCollection<T>(DependencyObject parent, List<T> visualCollection) where T : Visual
    {
        int count = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < count; i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(parent, i);
            if (child is T)
            {
                visualCollection.Add(child as T);
            }
            else if (child != null)
            {
                GetVisualChildCollection(child, visualCollection);
            }
        }
    }