2011-09-02 63 views
2

自己解决了。这是我初始化Settings集合的方式。将其注册为DependencyProperty时指定默认值会导致所有设置引用相同的集合对象。向类别添加构造函数并显式初始化设置可解决问题。WPF TreeView中重复的孩子


类别类别指定名称和Settings对象的集合。

using System.Collections.ObjectModel; 
using System.Windows; 

namespace CasEdit 
{ 
    public class Categories : ObservableCollection<Category> { } 

    public class Category : DependencyObject 
    { 
    public string Caption 
    { 
     get { return (string)GetValue(CategoryProperty); } 
     set { SetValue(CategoryProperty, value); } 
    } 
    public static readonly DependencyProperty CategoryProperty = 
     DependencyProperty.Register("Caption", typeof(string), typeof(Category), 
     new UIPropertyMetadata("Category name not set")); 
    public Settings Settings 
    { 
     get { return (Settings)GetValue(SettingsProperty); } 
    } 
    public static readonly DependencyProperty SettingsProperty = 
     DependencyProperty.Register("Settings", typeof(Settings), typeof(Category), 
     new UIPropertyMetadata(new Settings())); 
    } 
} 

以下XAML定义了模板,UI和一些测试数据。

<Window x:Class="CasEdit.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:CasEdit="clr-namespace:CasEdit" 
     Title="MainWindow" Height="350" Width="525" > 
    <Window.Resources> 
    <HierarchicalDataTemplate DataType="{x:Type CasEdit:Category}" ItemsSource="{Binding Settings}"> 
     <StackPanel Orientation="Horizontal"> 
     <TextBlock Text="{Binding Caption}" /> 
     <Button Content="Gratuitous button" Margin="3" Click="Button_Click"/> 
     </StackPanel> 
    </HierarchicalDataTemplate> 
    <DataTemplate DataType="{x:Type CasEdit:Setting}" > 
     <StackPanel Orientation="Horizontal"> 
     <TextBlock Text="{Binding Caption}" Margin="3" /> 
     <TextBlock Text="{Binding Template}" Margin="3" /> 
     <TextBox Text="{Binding Editor}" Margin="3" /> 
     <TextBlock Text="{Binding CasDevice}" Margin="3" /> 
     </StackPanel> 
    </DataTemplate> 
    <CasEdit:Categories x:Key="cats"> 
     <CasEdit:Category Caption="1st category"> 
     <CasEdit:Category.Settings> 
      <CasEdit:Setting Caption="Setting 1-1" /> 
      <CasEdit:Setting Caption="Setting 1-2" /> 
     </CasEdit:Category.Settings> 
     </CasEdit:Category> 
     <CasEdit:Category Caption="2nd category" > 
     <CasEdit:Category.Settings> 
      <CasEdit:Setting Caption="Setting 2-1" /> 
     </CasEdit:Category.Settings>   
     </CasEdit:Category> 
     <CasEdit:Category Caption="3rd category" > 
     <CasEdit:Category.Settings> 
      <CasEdit:Setting Caption="Setting 3-1" /> 
     </CasEdit:Category.Settings>   
     </CasEdit:Category> 
    </CasEdit:Categories> 
    </Window.Resources> 
    <Grid> 
    <TreeView x:Name="tree" ItemsSource="{Binding Source={StaticResource cats}}" /> 
    </Grid> 
</Window> 

你会想到树这样

  • 第一类
    • 设置1-1
    • 设置1-2
  • 第二类
    • 设置2-1
  • 第三类
    • 设置3-1

但我得到的是这种

Screen snap

这是非常混乱。我迷失在哪里,每个类别都显示了所有的设置?

回答

1

这里的最后一个参数告诉使得它使类别的每个实例有它的初始化指向同一个对象设置属性:

public static readonly DependencyProperty SettingsProperty = 
     DependencyProperty.Register("Settings", typeof(Settings), typeof(Category),  
     new UIPropertyMetadata(new Settings())); 

相反,这样做:

public static readonly DependencyProperty SettingsProperty = 
     DependencyProperty.Register("Settings", typeof(Settings), typeof(Category), 
     new UIPropertyMetadata(null)); 
    public Category() 
    { 
     Settings = new Settings(); 
    } 
+0

如果您看看问题的最后更新时间戳,你会发现我在发布问题后几乎立即得出了相同的结论,并在问题的顶部写下了这个问题。但你是正确的,也是第一个回答,所以我很乐意给你任何。 –

+0

@PeterWone:仅供将来参考,你不应该编辑你的问题的答案,用适当的答案回答你自己的问题,并接受它。 –

+0

系统不会让你在两个小时内回答自己的问题。在这种情况下,答案在发布问题后几秒钟就到了。 –