Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf TreeView和复合数据的奇怪无序行为_Wpf - Fatal编程技术网

Wpf TreeView和复合数据的奇怪无序行为

Wpf TreeView和复合数据的奇怪无序行为,wpf,Wpf,下面的代码加载一个层次结构集合,用于组合对象的集合,然后加载字符串的集合。但不幸的是,它在树的顶部而不是底部插入字符串(这是我一直看到的行为) 我尝试更改枚举器、通知器等的顺序,所有这些都会产生相同的结果。我已经预加载了列表,它看起来很正常(在线程中使用相同的代码) 你知道怎么回事吗 CompoundObject.cs using System; using System.Collections.Generic; using System.Collections.ObjectModel; usi

下面的代码加载一个层次结构集合,用于组合对象的集合,然后加载字符串的集合。但不幸的是,它在树的顶部而不是底部插入字符串(这是我一直看到的行为)

我尝试更改枚举器、通知器等的顺序,所有这些都会产生相同的结果。我已经预加载了列表,它看起来很正常(在线程中使用相同的代码)

你知道怎么回事吗

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;

    }



}
使用系统;
使用System.Collections.Generic;
使用System.Collections.ObjectModel;
使用System.Collections.Specialized;
使用System.Linq;
使用系统文本;
命名空间ComplexTreeViewLazyLoadingTest
{
公共类CompoundObject:IEnumerable,INotifyCollectionChanged
{
公共字符串名称{get;set;}
公共ObservableCollection对象{get;private set;}
公共可观测集合项{get;private set;}
更改后无效(对象发送方,NotifyCollectionChangedEventArgs e)
{ 
如果(CollectionChanged!=null)
App.Current.Dispatcher.Invoke((操作)((senderr,ee)=>{
收款已更改(发送人,ee);
}),发送者,e);
}
公共复合对象(字符串名称)
{ 
名称=名称;
Items=新的ObservableCollection();
对象=新的ObservableCollection();
Items.CollectionChanged+=新通知collectionchangedventhadler(一旦更改);
objects.CollectionChanged+=新的NotifyCollectionChangedEventHandler(OnChanged);
}
公共IEnumerator GetEnumerator()
{
如果(objects!=null)foreach(objects中的var a)产生返回值;
如果(Items!=null)foreach(Items中的var a)返回a;
屈服断裂;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator(){return GetEnumerator();}
公共事件通知CollectionChangedEventHandler 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;
        }
    }


}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
使用系统线程;
命名空间ComplexTreeViewLazyLoadingTest
{
公共部分类主窗口:窗口
{
CompoundObject c=新的CompoundObject(“根”);
公共主窗口()
{
初始化组件();
treeView.DataContext=c;
treeView.ItemsSource=c;
QueueUserWorkItem(新的WaitCallback(更新));
}
无效更新(对象数据)
{
对于(int i=0;i<10;i++)
{
Application.Current.Dispatcher.Invoke((操作)((cc)=>{
c、 对象。添加(cc);
}),新的复合对象(“对象”+i));
对于(int j=0;j<5;j++)
{
睡眠(100);
Application.Current.Dispatcher.Invoke((操作)((cc)=>
{
c、 objects[i].objects.Add(cc);
}),新的复合对象(“子对象”+j));
}
}
对于(int i=0;i<8;i++)
{
睡眠(250);
Application.Current.Dispatcher.Invoke((操作)((ii)=>
{
c、 项目。添加(“项目”+ii);
}),i.ToString());
}
}
}//主窗口
公共类DTS:DataTemplateSelector
{
公共覆盖数据模板SelectTemplate(对象项,DependencyObject容器)
{
FrameworkElement=容器作为FrameworkElement;
if(元素!=null&&item!=null)
{
如果(项为复合对象)
{
返回元素.FindResource(“CompoundTemplate”)作为DataTemplate;
}
如果(项目为int)
{
返回元素.FindResource(“DefaultTemplate”)作为DataTemplate;
}
}
返回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”的通知,而实际上您希望将其添加到列表的末尾。为了使此操作有效,您需要为每个子集合订阅CollectionChanged,并正确实现您自己的CollectionChanged回调(将第一个集合的计数添加到添加/删除字符串时报告的所有索引中。)

因为您要合并两个集合并直接订阅已更改的集合,所以更改通知是针对子列表的,而不是针对“合并”列表。这意味着您将收到一个通知,当您确实希望将其添加到列表末尾时,会在0处添加一个“字符串”。为了实现此功能,您需要使用子列表抄录到每个子集合的CollectionChanged,并正确执行您自己的CollectionChanged回调(将第一个集合的计数添加到添加/删除字符串时报告的所有索引中)。

谢谢,不100%确定您是否说了我所做的,但不知怎的,我用您的答案修复了它(至少您指出了正确的位置).NotifyCollectionChangedEventArgs被传递给要将项目添加到的索引。由于子集合相互了解,因此它们都