XAML. Иерархические модели для разных типов объектов

Всех приветствую! Столкнулся с такой задачей, над которой ломаю голову уже который день. Имеется следующая модель:

public class Part
{
    public int ID {get; set;}
    ... //Другие свойства
    public ObservableCollection<Part> Parts {get; set;}
    public ObservableCollection<Operation> Operations {get; set;}
}

public class Operation
{
    public int ID {get; set;}
    ... //Другие свойства
}

Так вот не могу разобраться с разметкой XAML. Использую TreeView для оформления иерархии объектов:

<UserControl x:Class="Therminal.Forms.PDO.SomeForms.PDO_PartTreeControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:Therminal.Forms.PDO.SomeForms"
         xmlns:partModels="clr-namespace:Therminal.Forms.PDO.StructurePart"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">



<UserControl.Resources>

</UserControl.Resources>


<TreeView x:Name="treeView1" Margin="2" BorderThickness="0" PreviewMouseRightButtonDown="Grid_PreviewMouseRightButtonDown"
              SelectedValuePath="ID" Grid.ColumnSpan="2">

    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />

            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                </Trigger>
            </Style.Triggers>
        </Style>
    </TreeView.ItemContainerStyle>



    <TreeView.ItemTemplate >
        <HierarchicalDataTemplate ItemsSource="{Binding Parts, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DataType="{x:Type partModels:Part_PDO}">
            <Grid  Height="20"  MouseLeftButtonDown="Grid_MouseLeftButtonDown" PreviewMouseLeftButtonDown="PreviewMLBDown" Background="#FF37A0BF">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="30"/>
                    <ColumnDefinition Width="Auto" MinWidth="150"/>
                    <ColumnDefinition Width="150"/>
                    <ColumnDefinition Width="40"/>
                    <ColumnDefinition Width="40"/>
                    <ColumnDefinition Width="40"/>
                    <ColumnDefinition Width="60"/>
                </Grid.ColumnDefinitions>

                <Border Grid.Column="0" Grid.Row="0" Width="Auto" Background="{Binding Color}" BorderThickness="1" BorderBrush="Black">
                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"  
                                   Text="{Binding ShortPartName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                </Border>

                <Border Grid.Column="1" Grid.Row="0" Background="Silver" BorderThickness="1" BorderBrush="Black">
                    <TextBlock HorizontalAlignment="Left" Margin="5,0,5,0" VerticalAlignment="Center"  
                                   Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                </Border>

                <Border Grid.Column="2" Grid.Row="0" Width="Auto" Background="Silver" BorderThickness="1" BorderBrush="Black">
                    <TextBlock HorizontalAlignment="Left" Margin="5,0,5,0" VerticalAlignment="Center" MaxWidth="200"
                                   Text="{Binding BlueprintName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                </Border>

                <Border Grid.Column="3" Grid.Row="0" Background="Silver" BorderThickness="1" BorderBrush="Black">
                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" MaxWidth="40" 
                                   Text="{Binding Amount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                </Border>

                <Border Grid.Column="4" Grid.Row="0" Background="{Binding PartVariantColor, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" BorderThickness="1" BorderBrush="Black">
                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" MaxWidth="40" 
                                   Text="{Binding OperationAmount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                </Border>
                <Border Grid.Column="5"  Grid.Row="0" Background="{Binding DistributedColor, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  BorderThickness="1" BorderBrush="Black">
                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" MaxWidth="40" 
                                   Text="{Binding DistributedAmount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                </Border>

                <Border Grid.Column="6" Grid.Row="0" Background="{Binding SupermarketItemColor, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  BorderThickness="1" BorderBrush="Black">
                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" MaxWidth="60" 
                                   Text="{Binding SupermarketItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                </Border>

                <Grid.ContextMenu>
                    <ContextMenu>
                        <MenuItem Header="Перенести" Click="Send_MenuItem_Click"/>
                        <MenuItem Header="Проверить операции" Click="CheckOperations_MenuItem_Click_1"/>
                        <Separator/>
                        <MenuItem Header="Удалить" Click="Delete_MenuItem_Click_1"/>
                        <MenuItem Header="Назначить Шаблон" Click="MenuItem_Click"/>
                    </ContextMenu>
                </Grid.ContextMenu>
            </Grid>

        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

Получаю следующий результат: введите сюда описание изображения

В разрезе деталей - всё отлично. Но при добавлении еще одного шаблона по типу объекта - выходит чушь. Мне нужно, чтобы каждый элемент Part можно было развернуть иерархию Operations. Где-то на просторах данного ресурса нашел пот такой вариант разметки XAML:

<UserControl x:Class="Therminal.Forms.PDO.SomeForms.PDO_PartTreeControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:Therminal.Forms.PDO.SomeForms"
         xmlns:partModels="clr-namespace:Therminal.Forms.PDO.StructurePart"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">



<UserControl.Resources>

</UserControl.Resources>


<TreeView x:Name="treeView1" Margin="2" BorderThickness="0" PreviewMouseRightButtonDown="Grid_PreviewMouseRightButtonDown"
              SelectedValuePath="ID" Grid.ColumnSpan="2">

    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />

            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                </Trigger>
            </Style.Triggers>
        </Style>
    </TreeView.ItemContainerStyle>



    <TreeView.ItemTemplate >
        <HierarchicalDataTemplate ItemsSource="{Binding Parts, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DataType="{x:Type partModels:Part_PDO}">
            <Grid  Height="20"  MouseLeftButtonDown="Grid_MouseLeftButtonDown" PreviewMouseLeftButtonDown="PreviewMLBDown" Background="#FF37A0BF">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="30"/>
                    <ColumnDefinition Width="Auto" MinWidth="150"/>
                    <ColumnDefinition Width="150"/>
                    <ColumnDefinition Width="40"/>
                    <ColumnDefinition Width="40"/>
                    <ColumnDefinition Width="40"/>
                    <ColumnDefinition Width="60"/>
                </Grid.ColumnDefinitions>

                <Border Grid.Column="0" Grid.Row="0" Width="Auto" Background="{Binding Color}" BorderThickness="1" BorderBrush="Black">
                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"  
                                   Text="{Binding ShortPartName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                </Border>

                <Border Grid.Column="1" Grid.Row="0" Background="Silver" BorderThickness="1" BorderBrush="Black">
                    <TextBlock HorizontalAlignment="Left" Margin="5,0,5,0" VerticalAlignment="Center"  
                                   Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                </Border>

                <Border Grid.Column="2" Grid.Row="0" Width="Auto" Background="Silver" BorderThickness="1" BorderBrush="Black">
                    <TextBlock HorizontalAlignment="Left" Margin="5,0,5,0" VerticalAlignment="Center" MaxWidth="200"
                                   Text="{Binding BlueprintName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                </Border>

                <Border Grid.Column="3" Grid.Row="0" Background="Silver" BorderThickness="1" BorderBrush="Black">
                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" MaxWidth="40" 
                                   Text="{Binding Amount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                </Border>

                <Border Grid.Column="4" Grid.Row="0" Background="{Binding PartVariantColor, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" BorderThickness="1" BorderBrush="Black">
                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" MaxWidth="40" 
                                   Text="{Binding OperationAmount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                </Border>
                <Border Grid.Column="5"  Grid.Row="0" Background="{Binding DistributedColor, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  BorderThickness="1" BorderBrush="Black">
                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" MaxWidth="40" 
                                   Text="{Binding DistributedAmount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                </Border>

                <Border Grid.Column="6" Grid.Row="0" Background="{Binding SupermarketItemColor, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  BorderThickness="1" BorderBrush="Black">
                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" MaxWidth="60" 
                                   Text="{Binding SupermarketItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                </Border>

                <Grid.ContextMenu>
                    <ContextMenu>
                        <MenuItem Header="Перенести" Click="Send_MenuItem_Click"/>
                        <MenuItem Header="Проверить операции" Click="CheckOperations_MenuItem_Click_1"/>
                        <Separator/>
                        <MenuItem Header="Удалить" Click="Delete_MenuItem_Click_1"/>
                        <MenuItem Header="Назначить Шаблон" Click="MenuItem_Click"/>
                    </ContextMenu>
                </Grid.ContextMenu>
            </Grid>

            <HierarchicalDataTemplate.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Operations, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DataType="{x:Type partModels:Operation_PDO}">
                    <Grid Height="20">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="40"/>
                            <ColumnDefinition Width="150"/>
                            <ColumnDefinition Width="150"/>
                            <ColumnDefinition Width="150"/>
                            <ColumnDefinition Width="40"/>
                        </Grid.ColumnDefinitions>

                        <Border Grid.Column="0" Grid.Row="0" Width="Auto" Background="#FFC7A76F" BorderThickness="1" BorderBrush="Black">
                            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"  
                                   Text="{Binding ID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                        </Border>

                        <Border Grid.Column="1" Grid.Row="0" Width="Auto" Background="#FFC7A76F" BorderThickness="1" BorderBrush="Black">
                            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"  
                                   Text="{Binding District, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                        </Border>

                        <Border Grid.Column="2" Grid.Row="0" Width="Auto" Background="#FFC7A76F" BorderThickness="1" BorderBrush="Black">
                            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"  
                                   Text="{Binding OperationName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                        </Border>

                        <Border Grid.Column="3" Grid.Row="0" Width="Auto" Background="#FFC7A76F" BorderThickness="1" BorderBrush="Black">
                            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"  
                                   Text="{Binding OperationPlace, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                        </Border>

                        <Border Grid.Column="4" Grid.Row="0" Width="Auto" Background="#FFC7A76F" BorderThickness="1" BorderBrush="Black">
                            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"  
                                   Text="{Binding OperationsAmount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                        </Border>

                    </Grid>
                </HierarchicalDataTemplate>
            </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

и вот получаемы результат:

введите сюда описание изображения

Мне же нужно, чтобы у каждого Part, в котором есть Operations были эти желтые строчки. Прошу помощи разобраться во всем этом ? Но и вся остальная структура отображалась корректно.


Ответы (1 шт):

Автор решения: Mikhail

покажу пример своей TreeView я для начала делал модель:

public class Node
{
    public ObservableCollection<Node>? SubNodes { get; }
    public string Title { get; }
    public string Article { get; }
  
    public Node(string title, string article)
    {
        Title = title;
        Article = article;
    }
    
    public Node(string title, string article, ObservableCollection<Node> subNodes)
    {
        Title = title;
        SubNodes = subNodes;
        Article = article;
    }
}

Далее создал внутри vm ObservableCollection:

 public ObservableCollection<Node> Nodes { get; } = new()
    {
        new Node("xxxxxx", "", new ObservableCollection<Node>
        {
            new Node("xxxxx", "", new ObservableCollection<Node>
            {
                new Node("xxxxx", "", new ObservableCollection<Node>
                {
                    new Node("xxxxx, 2 ряд.", "Арт. xxxx"), new Node("xxxx, 2 ряд.", "Арт. xxxx"),
                    
                }),

каждый новый Node внутри это подстрока некая. И во View как то так, проблем никаких нет при добавлении:

<TreeView ItemsSource="{Binding Nodes}" FontSize="16">
    <TreeView.ItemTemplate>
        <TreeDataTemplate ItemsSource="{Binding SubNodes}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Title}" Padding="0,5,0,0" Width="300" Height="25"
                           Background="Transparent" PointerPressed="InputElement_OnPointerPressed" />
                <TextBlock Text="{Binding Article}" VerticalAlignment="Center" Margin="20,0,0,0"></TextBlock>
            </StackPanel>
        </TreeDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>
→ Ссылка