WPF TreeViewHierarchicalDataTemplate - 여러 자녀 컬렉션이 있는 개체에 바인딩
나는 그것을 얻으려고 노력하고 있다.TreeView
모든 그룹이 중첩된 그룹을 표시하고 각 그룹이 엔트리를 표시하도록 내 컬렉션을 바인딩합니다.
어떻게 하면HierarchicalDataTemplate
그 때문에TreeView
서브그룹과 엔트리 컬렉션을 모두 처리합니까?
그룹은 서브그룹과 엔트리를 표시합니다.
Example:
Group1
--Entry
--Entry
Group2
--Group4
----Group1
------Entry
------Entry
----Entry
----Entry
--Entry
--Entry
Group3
--Entry
--Entry
오브젝트:
namespace TaskManager.Domain
{
public class Entry
{
public int Key { get; set; }
public string Name { get; set; }
}
}
namespace TaskManager.Domain
{
public class Group
{
public int Key { get; set; }
public string Name { get; set; }
public IList<Group> SubGroups { get; set; }
public IList<Entry> Entries { get; set; }
}
}
테스트 데이터:
namespace DrillDownView
{
public class TestData
{
public IList<Group> Groups = new List<Group>();
public void Load()
{
Group grp1 = new Group() { Key = 1, Name = "Group 1", SubGroups = new List<Group>(), Entries = new List<Entry>() };
Group grp2 = new Group() { Key = 2, Name = "Group 2", SubGroups = new List<Group>(), Entries = new List<Entry>() };
Group grp3 = new Group() { Key = 3, Name = "Group 3", SubGroups = new List<Group>(), Entries = new List<Entry>() };
Group grp4 = new Group() { Key = 4, Name = "Group 4", SubGroups = new List<Group>(), Entries = new List<Entry>() };
//grp1
grp1.Entries.Add(new Entry() { Key=1, Name="Entry number 1" });
grp1.Entries.Add(new Entry() { Key=2, Name="Entry number 2" });
grp1.Entries.Add(new Entry() { Key=3,Name="Entry number 3" });
//grp2
grp2.Entries.Add(new Entry(){ Key=4, Name = "Entry number 4"});
grp2.Entries.Add(new Entry(){ Key=5, Name = "Entry number 5"});
grp2.Entries.Add(new Entry(){ Key=6, Name = "Entry number 6"});
//grp3
grp3.Entries.Add(new Entry(){ Key=7, Name = "Entry number 7"});
grp3.Entries.Add(new Entry(){ Key=8, Name = "Entry number 8"});
grp3.Entries.Add(new Entry(){ Key=9, Name = "Entry number 9"});
//grp4
grp4.Entries.Add(new Entry(){ Key=10, Name = "Entry number 10"});
grp4.Entries.Add(new Entry(){ Key=11, Name = "Entry number 11"});
grp4.Entries.Add(new Entry(){ Key=12, Name = "Entry number 12"});
grp4.SubGroups.Add(grp1);
grp2.SubGroups.Add(grp4);
Groups.Add(grp1);
Groups.Add(grp2);
Groups.Add(grp3);
}
}
}
XAML:
<Window x:Class="DrillDownView.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TaskManager.Domain;assembly=TaskManager.Domain"
Title="Window2" Height="300" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TreeView Name="GroupView" Grid.Row="0" Grid.Column="0" ItemsSource="{Binding}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Group}" ItemsSource="{Binding SubGroups}">
<TextBlock Text="{Binding Path=Name}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Entry}" ItemsSource="{Binding Entries}">
<TextBlock Text="{Binding Path=Name}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
</Window>
XAML.CS:
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
LoadView();
}
private void LoadView()
{
TestData data = new TestData();
data.Load();
GroupView.ItemsSource = data.Groups;
}
}
A HierarchicalDataTemplate
는 '이러한 유형의 오브젝트를 렌더링하는 방법이며, 이 오브젝트 아래에 있는 하위 노드를 찾기 위해 프로빙할 수 있는 속성이 여기에 있습니다'라는 표현입니다.
따라서 이 노드의 '자녀'를 반환하는 단일 속성이 필요합니다(예: Group과 Entry를 모두 공통 노드 유형에서 파생할 수 없는 경우).
public class Group{ ....
public IList<object> Items
{
get
{
IList<object> childNodes = new List<object>();
foreach (var group in this.SubGroups)
childNodes.Add(group);
foreach (var entry in this.Entries)
childNodes.Add(entry);
return childNodes;
}
}
그 다음은 필요 없습니다.HierarchicalDataTemplate
아이가 없는 엔트리에 등록해야 합니다.따라서 새로운 Items 속성을 사용하려면 XAML을 변경해야 합니다.DataTemplate
엔트리:
<TreeView Name="GroupView" Grid.Row="0" Grid.Column="0" ItemsSource="{Binding}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Group}" ItemsSource="{Binding Items}">
<TextBlock Text="{Binding Path=Name}" />
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:Entry}" >
<TextBlock Text="{Binding Path=Name}" />
</DataTemplate>
</TreeView.Resources>
</TreeView>
이게 바로 그 모습입니다.
여기 Gishu의 답변에 대한 대체 구현이 있습니다.IEnumerable
가 아니라IList
, 및 를 사용합니다.yield
키워드를 지정하여 코드를 간략화합니다.
public class Group
{
...
public IEnumerable<object> Items
{
get
{
foreach (var group in this.SubGroups)
yield return group;
foreach (var entry in this.Entries)
yield return entry;
}
}
}
난 네가 거의 거기 있는 것 같아...약간의 재작업으로 이 작업을 꽤 쉽게 할 수 있을 것입니다.
기본 추상 클래스(또는 인터페이스(또는 원하는 경우)를 생성하여 Group 클래스와 Entry 클래스 모두에 대해 상속/실장할 것을 권장합니다.
이렇게 하면 Group 객체 내의 속성을 표시할 수 있습니다.
public ObservableCollection<ITreeViewItem> Children { get; set; }
^이 시점에서 서브그룹과 엔트리의 리스트를 대체할 것인지, 또는 그것들을 함께 추가하여 속성 게터에 반환할 것인지를 결정할 수 있습니다.
이제 Children 컬렉션에 Group 개체 또는 Entry 개체를 채우면 됩니다.HierarchicalDataTemplate
오브젝트가 TreeView에 배치되면 올바르게 렌더링됩니다.
마지막으로, 엔트리가 항상 트리의 '하위 레벨'인 경우(자녀 없음),HierarchicalDataTemplate
Entry 객체의 경우DataTemplate
충분합니다.
이것이 도움이 되기를 바랍니다:)
이 투고는 같은 문제에 대한 해결책을 찾을 때 도움이 되었습니다.http://blog.pmunin.com/2012/02/xaml-binding-to-compositecollection.html
MultiBinding 및 CompositeCollectionConverter 사용
언급URL : https://stackoverflow.com/questions/1912481/wpf-treeview-hierarchicaldatatemplate-binding-to-object-with-multiple-child-co
'code' 카테고리의 다른 글
VBA를 사용하여 지정된 셀 위치에서 Excel에 사진을 삽입하는 방법 (0) | 2023.04.13 |
---|---|
빈 텍스트 블록을 숨기는 방법 (0) | 2023.04.13 |
애니메이션으로 UIView 숨김/표시 (0) | 2023.04.13 |
SQL Server Express의 제한 사항 (0) | 2023.04.13 |
PowerShell: 텍스트 파일 내용 전체를 변수에 저장 (0) | 2023.04.08 |