PropertyChanged在TreeView中始终为null

时间:2015-06-11 08:46:07

标签: c# wpf xaml mvvm treeview

我在WPF项目的TreeView中实现搜索功能时遇到问题。

我使用this guide创建了一个带ViewModels的TreeView。我已经使用了TextSeachDemo并以适合我的应用程序的方式编辑了控件。 (添加了正确的类,更多层等。)

一切正常,我得到一个正确的孩子和父母的结构,搜索功能也可以,因为它找到了正确的条目。

现在的问题是:当我尝试从代码设置“IsExpanded”属性时没有任何反应。 Debubgging向我显示RaiseProperty Changed Method中的PropertyChanged事件始终为null。

在Josh Smith提供的测试项目中,一切似乎都运转正常。 我能解决的唯一显着差异是他在XAML中设置了datacontext代码:

Josh Smith的代码:

 public TextSearchDemoControl()
    {
        InitializeComponent();

        // Get raw family tree data from a database.
        Person rootPerson = Database.GetFamilyTree();

        // Create UI-friendly wrappers around the 
        // raw data objects (i.e. the view-model).
        _familyTree = new FamilyTreeViewModel(rootPerson);

        // Let the UI bind to the view-model.
        base.DataContext = _familyTree;
    }

来自MainViewModel的构造函数(处理整个窗口的ViewModel)

List<FactoryItem> rootItems = _machineService.GetFactoryItems();
  FactoryTree = new FactoryTreeViewModel(rootItems);

FactoryTree是一个公共的Observable属性,它也绑定了TreeView的DataContext(而不是上面的代码):

   <TreeView DataContext="{Binding FactoryTree}" ItemsSource="{Binding FirstGeneration}">

顺便说一下,当我通过GUI打开一个项目时,我的属性上的断点会触发并引发一个事件。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

此解决方案以更友好的mvvm方式解决问题。 UserControl包含TreeView。 它使用类型YourViewModel作为数据上下文。 视图模型包含YourDomainType的集合,其本身具有相同类型的子集合ChildElements

在xaml中,数据绑定到视图模型的ElementInViewModel集合。另外还有一个HierarchicalDataTemplate(适用于树视图)。

类型YourDomainType包含属性IsExpandedIsSelected,这些属性绑定到TreeViewItemStyle的相应属性。 如果在视图模型中设置这些属性,树视图应按预期反应(选择或展开相应的TreeViewItem)。

我知道IsExpandedIsSelected不属于DTO对象。 YourDomainType可能更像是一种显示数据的类型,但它也可以包装存储在其中的DTO对象。

<UserControl>

    <UserControl.DataContext>
        <YourViewModel/>
    </UserControl.DataContext>  

    <UserControl.Resources>        
        <CollectionViewSource Source="{Binding Path=ElementsInViewModel}" x:Key="Cvs">
        </CollectionViewSource>

        <HierarchicalDataTemplate DataType="{x:Type DomainModel:YourDomainType}"
                                  ItemsSource="{Binding Path=ChildElements}">
            <TextBlock Text="{Binding Path=Name}"/>            
        </HierarchicalDataTemplate>        

        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
            </Setter>
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
            </Setter>            
        </Style>

    </UserControl.Resources>


    <DockPanel>
        <TreeView ItemsSource="{Binding Source={StaticResource Cvs}}"/>
    </DockPanel>

</UserControl>

public class YourViewModel
{

    public ObservableCollection<YourDomainType> ElementsInViewModel 
    {
        get
        {
            return _elementsInViewModel;
        }
        set
        {
            if (_elementsInViewModel != value)
            {
                _elementsInViewModel = value;
                RaisePropertyChanged("ElementsInViewModel");
            }
        }
    }
    ObservableCollection<YourDomainType> _elementsInViewModel;


    public YourViewModel()
    {

    }
}

public class YourDomainType
{

    public ObservableCollection<YourDomainType> ChildElements
    {
        get
        {
            return _childElements;
        }
        set
        {
            if (_childElements != value)
            {
                _childElements = value;
                RaisePropertyChanged("ChildElements");
            }
        }
    }
    ObservableCollection<YourDomainType> _childElements;


    public bool IsExpanded
    {
        get
        {
            return _isExpanded;
        }
        set
        {
            if (_isExpanded != value)
            {
                _isExpanded = value;
                RaisePropertyChanged("IsExpanded");
            }
        }
    }
    bool _isExpanded;


    public bool IsSelected
    {
        get
        {
            return _isSelected;
        }
        set
        {
            if (_isSelected != value)
            {
                _isSelected = value;
                RaisePropertyChanged("IsSelected");
            }
        }
    }
    bool _isSelected;


    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            if (_name != value)
            {
                _name = value;
                RaisePropertyChanged("Name");
            }
        }
    }
    string _name;
}