문제

객체 데이터 핀딩으로 WPF TreeView를 만드는 데 심각한 어려움이 있습니다.

응용 프로그램은 구성 파일 편집기입니다. 올바른 XML 형식으로 직렬화 될 수있는 객체 구조를 정의했습니다.

내가 가지고있는 문제는 올바른 계층 구조를 보여주는 treeview에서 개체 인스턴스를 서식하는 것입니다. TreeView는 채널 노드 만 렌더링합니다.

public class Objects
{
    public List<Channel> Channels { get; set; }
}

public class Channel 
{
    public string Id { get; set; }
    public string Name { get; set; }
    public Reader Reader { get; set; }
    public Filters Filters { get; set; }
    public Router Router { get; set; }
    public Persister Persister { get; set; }
}

public class Filters : ArrayList
{
    public string StopOnFailure { get; set; }
}

public class Reader
{
    public string Id { get; set; }
    public string Name { get; set; }
}

모든 어린이 수업 Channel 속성을 포함합니다 Id 그리고 Name. 필터 클래스는 동일한 속성 정의를 가진 다른 유형의 모음입니다.

여기 XAML이 있습니다

 <Window.Resources>
    <ObjectDataProvider x:Key="data"/>
    <DataTemplate DataType="{x:Type ConfigurationEditor:Channel}">
        <WrapPanel>
            <TextBlock FontWeight="Bold" Text="{Binding Path=Name}" />
            <TextBlock Text=" [" />
            <TextBlock  Text="{Binding Path=Id}" />
            <TextBlock Text="]" />
        </WrapPanel>
    </DataTemplate>
    <DataTemplate DataType="{x:Type ConfigurationEditor:Reader}">
        <TextBlock Text="{Binding Path=Name}"/>
    </DataTemplate>
</Window.Resources>
<Grid>
    <TreeView Margin="12,12,12,96" Name="treeView1" ItemsSource="{Binding Source={StaticResource data}, Path=Channels}">
    </TreeView>
</Grid>

데이터 인스턴스를 만들기위한 코드

Objects config;
var serializer = new XmlSerializer(typeof(Objects));
using (var stream = new FileStream(@"C:\test.xml", FileMode.Open))
{
    config = (Objects)serializer.Deserialize(stream);
}

var dp = (ObjectDataProvider)FindResource("data");
dp.ObjectInstance = config;

나는 수많은 예를 살펴 보았지만 여전히 내가 무엇을 잘못하고 있는지 알아낼 수 있습니다. 도와 주셔서 감사합니다.

업데이트:

<HierarchicalDataTemplate DataType="{x:Type ConfigurationEditor:Objects}" ItemsSource="{Binding Path=Channels}"/>
<HierarchicalDataTemplate DataType="{x:Type ConfigurationEditor:Channel}" ItemsSource="Binding Path=Reader}">
    <TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>

<DataTemplate DataType="{x:Type ConfigurationEditor:Reader}">
    <TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>

변경 사항이 없습니다 TreeView. 이 변화로 나는 여전히 만 있습니다 Channel 나열되어 있고 다른 것은 없습니다.

도움이 되었습니까?

해결책

@limalay의 답변을 확장하면 문제는 TreeView 자식 노드의 데이터를 어디서 얻을 수 있는지 모릅니다. 당신은 알립니다 TreeView a HierarchialDataTemplate, a보다는 DataTemplate:

<HierarchialDataTemplate DataType="{x:Type ConfigurationEditor:Channel}"
    ItemsSource="...">
    <WrapPanel>
        <TextBlock FontWeight="Bold" Text="{Binding Path=Name}" />
        <TextBlock Text=" [" />
        <TextBlock  Text="{Binding Path=Id}" />
        <TextBlock Text="]" />
    </WrapPanel>
</HierarchialDataTemplate>

둘의 주요 차이점은입니다 ItemsSource 기인하다. 이것은 하위 노드로 사용할 객체 모음을 반환하는 바인딩 표현입니다.

문제는 어린이를 하나뿐만 아니라 자녀를 얻을 수있는 속성이 몇 개 있다는 것입니다. 당신은 그것들을 하나의 속성에 결합하거나 모든 자식 노드를 반환하는 다른 속성을 추가해야합니다.

마지막으로 a를 정의해야합니다 DataTemplate 각 어린이 항목 유형에 대해 TreeView 표시하는 방법을 알고 있습니다 (사용할 수 있습니다. HierarchialDataTemplate 어린이들에게도 자녀 노드가 있다면).

다른 팁

객체가 TreeView의 그림에 들어오지 않기 때문에이 템플릿이 필요하다고 생각하지 않습니다.

<HierarchicalDataTemplate
    DataType="{x:Type ConfigurationEditor:Objects}" 
    ItemsSource="{Binding Path=Channels}"/>

당신은 이것을 XAML로 설정했습니다.

<TreeView 
    Margin="12,12,12,96" Name="treeView1" 
    ItemsSource="{Binding Source={StaticResource data}, Path=Channels}">
</TreeView>

이제 독자도 보여주기를 원합니다. 그러나 ienumerable 유형의 객체 만 ItemsSource로만 지정할 수 있습니다., 따라서 아래 템플릿이 잘못되어 "Reader"를 ItemsSource로 지정합니다.

<HierarchicalDataTemplate 
    DataType="{x:Type ConfigurationEditor:Channel}" 
    ItemsSource="{Binding Path=Reader}">
    <TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>

따라서 독자 이름도 표시 되려면 아래와 같이 템플릿을 사용하십시오.

<DataTemplate 
    DataType="{x:Type ConfigurationEditor:Channel}" >
    <StackPanel>
        <TextBlock Text="{Binding Path=Name}"/>
        <TextBlock Text="{Binding Path=Reader.Name}"/>
    <StackPanel>
</DataTemplate>

이를 위해 항목 소스에 실제로 계층 구조가있을 때 계층 적 데이터 템플릿이 사용됩니다. 즉, 객체 자체는 계층 구조를 가지고 있으며, 부모 객체는 자식 객체 목록을 유지합니다.

예를 들어, 각 채널에는 아래와 같은 속성 하위 채널이있을 수 있습니다.

public class Channel 
{
    public string Id { get; set; }
    public string Name { get; set; }
    public ObservableCollection<Channel> SubChannels { get; }
}

그런 다음 우리는 이와 같은 템플릿을 사용할 수있었습니다.

<HierarchicalDataTemplate 
    DataType="{x:Type ConfigurationEditor:Channel}" 
    ItemsSource="{Binding Path=SubChannels}">
    <TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>

이제 객체 구조는 각 서브 채널에 다시 하위 채널을 갖는 다단계 깊이 일 수 있습니다.

또한 예제에서 나는 동일한 유형의 채널을 사용하여 서브 채널의 계층 구조를 만들었습니다. 우리는 다른 유형을 사용할 수있었습니다. 각 채널에 독자 목록이 있다고 말합니다.

좋아, 많은 시험 후에 나는 이것을 내가 원하는대로 작동하게 할 수 있었다. 내가 한 방법은 다음과 같습니다.

Channel 객체 나는 TreeView에 표시하고 싶은 다른 모든 속성의 모음 인 새 속성을 추가했습니다.

public ArrayList Components
{
    get { return new ArrayList { Reader, Filters, Router, Persister  }; } 
    set
    {
        ArrayList list = value;
        if (list != null)
        {
            foreach (var item in list)
            {
                if (item is Reader)
                {
                    Reader = (Reader)item;
                }
                else if (item is Router)
                {
                    Router = (Router) item;
                }
                else if (item is Persister)
                {
                    Persister = (Persister) item;
                }
                else if (item is Filters)
                {
                    Filters = (Filters) item;
                }
            }
        }
    }
}

그런 다음 내 XAML은 다음과 같습니다. TreeView를 표시합니다.

    <HierarchicalDataTemplate DataType="{x:Type ConfigurationEditor:Channel}" ItemsSource="{Binding Path=Components}">
        <WrapPanel>
            <TextBlock FontWeight="Bold" Text="{Binding Path=Name}" />
            <TextBlock Text=" [" />
            <TextBlock  Text="{Binding Path=Id}" />
            <TextBlock Text="]" />
        </WrapPanel>
    </HierarchicalDataTemplate>
    <HierarchicalDataTemplate DataType="{x:Type ConfigurationEditor:Filters}" ItemsSource="{Binding Path=.}">
        <TextBlock Text="Filters"/>
        <HierarchicalDataTemplate.ItemTemplate>
            <DataTemplate >
                <TextBlock Text="{Binding Path=Name}"/>
            </DataTemplate>
        </HierarchicalDataTemplate.ItemTemplate>
    </HierarchicalDataTemplate>
    <DataTemplate DataType="{x:Type ConfigurationEditor:Reader}">
        <TextBlock Text="{Binding Path=Name}"/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type ConfigurationEditor:Router}">
        <TextBlock Text="{Binding Path=Name}"/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type ConfigurationEditor:Persister}">
        <TextBlock Text="{Binding Path=Name}"/>
    </DataTemplate>

앤디에게 올바른 길을 가셔서 감사합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top