2009-09-13 6 views
2

Object databinding으로 WPF TreeView를 만드는 데 심각한 문제가 있습니다.TreeView가 객체 계층 구조를 표시하지 않습니다.

응용 프로그램은 설정 파일 편집기입니다. 올바른 XML 형식으로 serialize 할 수있는 Object 구조를 정의했습니다.

문제는 올바른 계층 구조를 보여주는 TreeView에서 개체 인스턴스의 서식을 지정하는 것입니다. TreeView는 Channel 노드 만 렌더링하고 다른 것은 렌더링하지 않습니다. Channel

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; } 
} 

모든 자식 클래스 속성을 IdName이 포함되어 있습니다. Filters 클래스는 동일한 속성 정의가있는 다른 유형의 컬렉션입니다.

다음은 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 만 나열하고 그 밖의 것은 없습니다.

+1

Nitpicking 조금 있지만 게시물에서 "WCF"텍스트를 "WPF"로 바꾸십시오. WCF와 WPF는 별도의 기술입니다. –

+0

@David : 혼란을 피하기 위해 그것을 고쳤습니다. – Andy

답변

2

확대 @ Gimalay의 답변에서 문제는 TreeView이 하위 노드의 데이터를 가져올 위치를 알 수 없다는 것입니다. 당신은 오히려 DataTemplate보다는 HierarchialDataTemplate를 사용하여 TreeView 통보 :

<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 속성입니다. 이것은 자식 노드로 사용할 객체의 컬렉션을 반환하는 바인딩 표현식입니다.

문제는 하나뿐 아니라 자녀를 데려 오기위한 몇 가지 속성이 있다는 것입니다. 모두 하나의 속성으로 결합하거나 모든 자식 노드를 반환하는 다른 속성을 추가해야합니다.

마지막으로, TreeView이 (가 차례로 자식 노드가있는 경우는,뿐만 아니라 아이들을위한 HierarchialDataTemplate을 사용할 수 있습니다)를 표시하는 방법을 알 수 있도록, 각 하위 항목 유형에 대한 DataTemplate을 정의해야합니다.

+0

'Objects' 클래스는'Channel' 객체들의 집합을 가진 하나의 속성을 가지고 있습니다. 그래서 그 유형과 속성을 사용하여'HierarchialDataTemplate'을 만들었습니다. 다른 템플릿을 추가하여'Channel' 노드를 표시 할 수 있지만 리프 노드는 여전히 표시되지 않습니다. – Karl

+0

업데이트 된 코드를 게시 할 수 있습니까? 이 문제를 디버그하는 데 도움이 될 수 있습니다. – Andy

2

개체가 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으로 지정할 수 있으므로 아래 템플릿은 ItemsSource로 "Reader"를 지정하는 잘못된 것입니다.

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

독자 이름을 표시하려면 아래 그림과 같이 템플릿을 사용하십시오.

+0

귀하의 의견에 감사드립니다, 그것은 도움이되었지만 달성하려는 효과가 아닙니다. 궁극적으로'Channel' 객체를 트리로 복제하려고합니다. 즉'Channel'의 모든 속성은 TreeView에서 자식 노드로 나타납니다. 당신이 준 예제에서'Reader' 이름은'Channel'과 같은 레벨에 나타납니다. 아래에서 작성한 설명을 통해 내가하려는 일이 불가능할 수도 있습니다. – Karl

0

계층 구조 데이터 템플릿은 항목 소스가 실제로 계층 구조를 가질 때 사용됩니다. 즉, 개체 자체에는 일부 개체가 들어있는 부모 개체가있는 계층 구조가 있습니다.

예를 들어, 각 채널은 아래처럼 속성 SubChannels를 가질 수 있습니다.

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> 

이제 객체 구조는 각 서브 채널이 다시 서브 채널을 갖는 다중 레벨 깊이 일 수 있습니다.

또한 예에서 방금 동일한 유형의 채널 인 채널을 사용하여 하위 채널 계층을 만들었습니다. 우리는 독자 유형 목록이있는 각 채널에 대해 다른 유형을 사용할 수있었습니다.

0

오케이, 많은 시행 착오 끝에 내가 원하는만큼 제대로 작동하지 못했습니다. 여기 내가 어떻게 했어. 내 Channel 객체에서

은 내가 트리 뷰를 표시하기 위해 다음과 같이

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 인 트 리뷰에 표시하고 싶어 다른 모든 속성의 컬렉션이었다 새 속성을 추가했다.

<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> 

감사합니다. 제대로 된 트랙에 나를 올려 주셔서 감사합니다.

관련 문제