Search code examples
regexwpfrecursiontreeviewdatatemplate

Why TreeView becomes recursive when it displays Regex matches?


I tried to make app for testing regular expression

by using TreeView to display MatchCollection to window

But it does not work correctly

App.xaml

<Application x:Class="RegularExpressionTester.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:RegularExpressionTester"
         xmlns:Regex="clr-namespace:System.Text.RegularExpressions;assembly=System"
         StartupUri="MainWindow.xaml">
<Application.Resources>
    <local:MainViewModel x:Key="MainViewModel"/>

    <HierarchicalDataTemplate DataType="{x:Type Regex:Match}"  ItemsSource="{Binding Path=Groups}">
        <TextBlock Text="{Binding Path=Value, StringFormat=[{0}](Match)}"/>
    </HierarchicalDataTemplate>
    <HierarchicalDataTemplate DataType="{x:Type Regex:Group}"  ItemsSource="{Binding Path=Captures}">
        <TextBlock Text="{Binding Path=Value, StringFormat=[{0}](Group)}"/>
    </HierarchicalDataTemplate>
    <HierarchicalDataTemplate DataType="{x:Type Regex:Capture}">
        <TextBlock Text="{Binding Path=Value, StringFormat=[{0}](Capture)}"/>
    </HierarchicalDataTemplate>
</Application.Resources>

Result:

Real Application

I want to display like this (expected result)

▶ Match

..▶ Group

....▶ Capture

▶ Match

..▶ Group

....▶ Capture

How I can do?


Solution

  • why is it possible to get infinite hierarhy?

    it is due to structure of Match.Groups and Group.Captures

    The Match instance itself is equivalent to the first object in the collection, at Match.Groups[0]

    from Match class - Remarks

    the Group instance is equivalent to the last item of the collection returned by the Captures property, which reflects the last capture made by the capturing group

    from Group class - Remarks

    how to fix?

    modify Templates like this:

    <HierarchicalDataTemplate DataType="{x:Type Regex:Match}"  
                                ItemsSource="{Binding Path=Groups}">
    
        <TextBlock Text="{Binding Path=Value, StringFormat=[{0}](Match)}"/>
    
        <HierarchicalDataTemplate.ItemTemplate>
            <HierarchicalDataTemplate DataType="{x:Type Regex:Group}"  
                                ItemsSource="{Binding Path=Captures}">
                    
                <TextBlock Text="{Binding Path=Value, StringFormat=[{0}](Group)}"/>
                    
                <HierarchicalDataTemplate.ItemTemplate>
                    <DataTemplate DataType="{x:Type Regex:Capture}">
                        <TextBlock Text="{Binding Path=Value, StringFormat=[{0}](Capture)}"/>
                    </DataTemplate>
                </HierarchicalDataTemplate.ItemTemplate>
    
            </HierarchicalDataTemplate>
        </HierarchicalDataTemplate.ItemTemplate>
    
    </HierarchicalDataTemplate>