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 шт):
покажу пример своей 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>

