项目来源 + 转换器 + 树形视图不会更新
这个问题相当复杂,希望我能说得足够清楚,以便有人帮助我。 我有一个对象,我们称之为经理,经理有他管理的人员的集合,这些人员都实现了 IPerson,但不同类型的人员具有不同的属性。 我想在树中显示这个经理,在经理节点下我想显示他正在管理的所有项目,这些项目可以从他管理的人员中确定。
所以计划是使用转换器将一个人转换为一个项目列表。 下面是 XAML:
<HierarchicalDataTemplate DataType="{x:Type ui:Manager}">
<TextBlock Text="{Binding Path=Name}"/>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate.ItemsSource>
<Binding Path="People">
<Binding.Converter>
<configUtil:ProjectListConverter/>
</Binding.Converter>
</Binding>
</HierarchicalDataTemplate.ItemsSource>
</HierarchicalDataTemplate>
我的 Person 类实现了 INotifyPropertyChanged,持有人员的列表实现了 INotifyCollectionChanged。当我设置树视图 ItemsSource 时,此代码效果很好,经理会显示其项目列表。
但是,当我将新人员添加到人员列表中时,TreeView 不会更新。 当我调试时,我可以看到 CollectionChanged 正在通过“添加”操作和添加的项目触发。 另外,CollectionChanged 事件不为空,因此我知道 UI 正在监视它。 但是添加项目时转换器不会执行。
这是保存 IPerson 对象的 List 的 Add 方法:
public void Add(T item)
{
list.Add(item);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
}
我是否以某种方式破坏了数据绑定?
我还可以检查哪些其他事项?
转换器仅查看人员列表中的每个项目,并找出他们正在处理哪些项目,并将项目名称添加到输出列表中。
This one is fairly complex, hopefully I can make this clear enough for somebody to help me out. I have an object lets call it a Manager, the Manager has a collection of people that he manages, the people all implement IPerson, but different types of people have different properties. I want to display this manager in a tree, and under the manager node I want to show all the projects he is managing which can be determined from the people he manages.
So the plan is to use a converter to convert a person into a List of projects. Here is the XAML:
<HierarchicalDataTemplate DataType="{x:Type ui:Manager}">
<TextBlock Text="{Binding Path=Name}"/>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate.ItemsSource>
<Binding Path="People">
<Binding.Converter>
<configUtil:ProjectListConverter/>
</Binding.Converter>
</Binding>
</HierarchicalDataTemplate.ItemsSource>
</HierarchicalDataTemplate>
My Person class implements INotifyPropertyChanged, and the list holding the people implements INotifyCollectionChanged.This code works great when I set the treeview ItemsSource, the Managers are displayed with their list of projects.
However, when I add a new person to the list of people, the TreeView is not updated. When I debug, I can see that the CollectionChanged is firing with the Add action and the added item. Also the CollectionChanged event is not null so I know the UI is watching it. But the Converter does not execute when the item is added.
here is the Add method for the List holding the IPerson objects:
public void Add(T item)
{
list.Add(item);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
}
Am I somehow breaking the databinding?
What other things can I check for?
The Converter just looks at each item in the People list and figures out what projects they are working on and adds the project name to an output List.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
该转换器应用于存储集合的属性。 因此,只有当集合实例本身发生更改(而不是集合中的项目发生更改)时才会调用它。 解决这个问题的一种方法是当您希望刷新集合时使集合无效。
使集合属性无效并导致转换器代码再次运行的最简单方法是将集合
null
取出并重新分配它。 另一种方法是获取BindingExpression
(通过
BindingOperations
)并调用更新目标
。 最后,您可以绑定到CollectionView
(或其子类)并调用刷新
就可以了。如果您真的想彻底解决问题,您可以绑定到您自己的
ICollectionView
进行过滤并根据需要引发事件。The converter is applied to the property that stores the collection. Therefore, it will only be called if the collection instance itself changes (not if items in the collection are changed). One way around this would be to invalidate the collection when you want it to refresh.
The simplest way to invalidate the collection property and cause the converter code to run again would be to
null
out the collection and reassign it. Another way is to get theBindingExpression
(viaBindingOperations
) and callUpdateTarget
. Finally, you could instead bind to aCollectionView
(or subclass thereof) and callRefresh
on it.And if you really want to fix the problem cleanly, you could bind to your own implementation of
ICollectionView
which does the filtering and raises events as necessary.