以下代码加载了CompoundObjects的分层集合,然后是字符串。但不幸的是,它将字符串插入树的顶部而不是底部(这是我一直看到的行为。
我试图改变枚举器,通知器等的顺序,并且都产生相同的结果。我已预先加载它看起来正常的列表(在线程中使用相同的代码)。
有什么想法吗?
CompoundObject.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
namespace ComplexTreeViewLazyLoadingTest
{
public class CompoundObject : IEnumerable<object>, INotifyCollectionChanged
{
public string Name { get; set; }
public ObservableCollection<CompoundObject> objects { get; private set; }
public ObservableCollection<string> Items { get; private set; }
void OnChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (CollectionChanged != null)
App.Current.Dispatcher.Invoke((Action<object, NotifyCollectionChangedEventArgs>)((senderr, ee) => {
CollectionChanged(senderr, ee);
}), sender, e);
}
public CompoundObject(string name)
{
Name = name;
Items = new ObservableCollection<string>();
objects = new ObservableCollection<CompoundObject>();
Items.CollectionChanged += new NotifyCollectionChangedEventHandler(OnChanged);
objects.CollectionChanged += new NotifyCollectionChangedEventHandler(OnChanged);
}
public IEnumerator<object> GetEnumerator()
{
if (objects != null) foreach(var a in objects) yield return a;
if (Items != null) foreach (var a in Items) yield return a;
yield break;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }
public event NotifyCollectionChangedEventHandler CollectionChanged;
}
}
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
namespace ComplexTreeViewLazyLoadingTest
{
public partial class MainWindow : Window
{
CompoundObject c = new CompoundObject("Root");
public MainWindow()
{
InitializeComponent();
treeView.DataContext = c;
treeView.ItemsSource = c;
ThreadPool.QueueUserWorkItem(new WaitCallback(Update));
}
void Update(object data)
{
for (int i = 0; i < 10; i++)
{
Application.Current.Dispatcher.Invoke((Action<CompoundObject>)((cc) => {
c.objects.Add(cc);
}), new CompoundObject("Object " + i));
for (int j = 0; j < 5; j++)
{
Thread.Sleep(100);
Application.Current.Dispatcher.Invoke((Action<CompoundObject>)((cc) =>
{
c.objects[i].objects.Add(cc);
}), new CompoundObject("subObject " + j));
}
}
for (int i = 0; i < 8; i++)
{
Thread.Sleep(250);
Application.Current.Dispatcher.Invoke((Action<string>)((ii) =>
{
c.Items.Add("Item " + ii);
}), i.ToString());
}
}
} // MainWindow
public class DTS : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
FrameworkElement element = container as FrameworkElement;
if (element != null && item != null)
{
if (item is CompoundObject)
{
return element.FindResource("CompoundTemplate") as DataTemplate;
}
if (item is int)
{
return element.FindResource("DefaultTemplate") as DataTemplate;
}
}
return null;
}
}
}
MainWindow.xaml
<Window x:Class="ComplexTreeViewLazyLoadingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ComplexTreeViewLazyLoadingTest;assembly="
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:DTS x:Key="DTS"/>
<HierarchicalDataTemplate x:Key="CompoundTemplate" ItemsSource="{Binding Path=.}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="DefaultTemplate" ItemsSource="{Binding Path=.}">
<TextBlock Text="{Binding Path=.}" Background="Aqua" />
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView Name="treeView" ItemTemplateSelector="{StaticResource DTS}"/>
</Grid>
</Window>
答案 0 :(得分:1)
因为您正在组合两个集合并直接订阅CollectionChanged,所以更改通知是针对子列表而不是“组合”列表。这意味着当您真正想要在列表末尾添加时,您将收到“字符串添加为0”的通知。为了使这项工作,您需要为每个子集合订阅CollectionChanged并正确实现您自己的CollectionChanged回调(将第一个集合的Count添加到添加/删除字符串时报告的所有索引。)