Wpf 数据虚拟化和ListView UI冻结

Wpf 数据虚拟化和ListView UI冻结,wpf,Wpf,我试图找到一个异步数据提供程序的解决方案,但everywhere绑定到一个静态类,但我需要一个到不同对象的动态绑定 我试图使用,但我的用户界面仍然冻结。任何人都可以解释我为什么会有这种行为,以及如何激活UI。 应用程序XAML文件: <Window x:Class="WpfApplication_async.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

我试图找到一个异步数据提供程序的解决方案,但everywhere绑定到一个静态类,但我需要一个到不同对象的动态绑定

我试图使用,但我的用户界面仍然冻结。任何人都可以解释我为什么会有这种行为,以及如何激活UI。 应用程序XAML文件:

    <Window x:Class="WpfApplication_async.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication_async"
        Title="MainWindow" Height="350" Width="525">
  <Window.Resources>
    <local:RecordValueDataTemplateSelector x:Key="myDataTemplateSelector"/>
    <DataTemplate x:Key="ComboBoxTemplate">
      <ComboBox Width="{Binding Path=ColumnDef.ColumnWidth,Mode=OneTime}"
                ItemsSource="{Binding Path=viewEntityList,Mode=TwoWay}" 
                SelectedIndex="{Binding Path=Index, Mode=TwoWay}">
      </ComboBox>
    </DataTemplate>
    <DataTemplate x:Key="TextBoxTemplate">
      <TextBox Text="{Binding Path=Text,Mode=TwoWay}" Width="{Binding Path=ColumnDef.ColumnWidth,Mode=OneTime}"/>
    </DataTemplate>
    <DataTemplate x:Key="HeaderTextBlockTemplate">
      <TextBlock Width="{Binding Path=ColumnWidth,Mode=OneTime}" Text="{Binding Path=ColumnName,Mode=TwoWay}" ToolTip="{Binding Path=ColumnName}" />
    </DataTemplate>
    <DataTemplate x:Key="ListBoxTemplate">
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Path=Key, Mode=TwoWay, 
          UpdateSourceTrigger=PropertyChanged}" Width="80"/>
        <ListBox ItemsSource="{Binding Path=Items}"
                 ItemTemplateSelector="{StaticResource myDataTemplateSelector}" 
                 ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                 ScrollViewer.CanContentScroll="False" >
          <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
              <StackPanel Orientation="Horizontal">
              </StackPanel>
            </ItemsPanelTemplate>
          </ListBox.ItemsPanel>
        </ListBox>
      </StackPanel>
    </DataTemplate>
  </Window.Resources>
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition></RowDefinition>
      <RowDefinition Height="Auto"></RowDefinition>
    </Grid.RowDefinitions>
    <ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Visible">
      <DockPanel>
        <ListBox Name="headerListBox" MinHeight="20" DockPanel.Dock="Top"  
                 ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                 ScrollViewer.CanContentScroll="False"
                 ItemTemplate="{StaticResource HeaderTextBlockTemplate}">
          <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
              <StackPanel Orientation="Horizontal"></StackPanel>
            </ItemsPanelTemplate>
          </ListBox.ItemsPanel>
        </ListBox>
        <ScrollViewer Name="listScrollViewer" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Visible">
          <ListView Name="listView" SelectionMode="Extended"
            VirtualizingStackPanel.IsVirtualizing="True"
            ScrollViewer.IsDeferredScrollingEnabled="True"
            VirtualizingStackPanel.VirtualizationMode="Recycling"
            ItemsSource="{Binding}"
            ItemTemplate="{StaticResource ListBoxTemplate}" >
          </ListView>
        </ScrollViewer>
      </DockPanel>
    </ScrollViewer>
    <Button Grid.Row="1" Content="Button" Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
  </Grid>
</Window>

我的数据提供程序类:

using System;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Specialized;
using System.Windows.Data;
using System.Windows;
using DataVirtualization;
using System.Threading;
//using System.Threading;

namespace WpfApplication_async
{
  public enum MySubKeyValueType { StringValue=0, ListValue=1 }

  public class MySection : IItemsProvider<MyRecord>
  {
    /// <summary>
    /// Fetches the total number of items available.
    /// </summary>
    /// <returns></returns>
    public int FetchCount()
    {
      //Thread.Sleep(1000);
      return Records.Count;
    }
    /// <summary>
    /// Fetches a range of items.
    /// </summary>
    /// <param name="startIndex">The start index.</param>
    /// <param name="count">The number of items to fetch.</param>
    /// <returns></returns>
    public IList<MyRecord> FetchRange(int startIndex, int count)
    {
      //Thread.Sleep(1000);
      if (startIndex > Records.Count) startIndex = Records.Count;
      if (startIndex + count > Records.Count) count = Records.Count - startIndex;
      return Records.ToList().GetRange(startIndex, count).ToList();
    }
    public MySection()
    {
      Records = new ObservableCollection<MyRecord>();
    }
    public ObservableCollection<MyRecord> Records { get; set;}
  }

  public class MyRecord : INotifyPropertyChanged
  {
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string info)
    {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null)
      {
        handler(this, new PropertyChangedEventArgs(info));
      }
    }
    public MyRecord() 
    {
      Items = new ObservableCollection<MySubKeyValue>();
    }
    private string key;
    public string Key { 
      get { 
        return key; 
      } 
      set {
        //if (Key!=null && this.Parent is MySection && (this.Parent as MySection).SectionDefinition.IsNumberedKeys)
        //  return;
        key = value;
        OnPropertyChanged("Key");
      } 
    }
    ObservableCollection<MySubKeyValue> items = new ObservableCollection<MySubKeyValue>();
    public ObservableCollection<MySubKeyValue> Items
    {
      get {
        return items;
      }
      set {
        items = value;
        OnPropertyChanged("NumberedColumnText");
      }
    } 
  }

  public class MySubKeyValue : DependencyObject, INotifyPropertyChanged
  {
    private ColumnDefinition columnDef = null;
    public ColumnDefinition ColumnDef
    {
      get
      {
        if (columnDef == null)
          return columnDef = new ColumnDefinition();
        return columnDef;
      }
      set { columnDef = value; }
    }
    public MySubKeyValue(string str = null)
    {
      Text = str;
      ValueType = MySubKeyValueType.StringValue;
      IsValidData = true;
      ErrorMessage = "error";
    }
    private string text;
    public MySubKeyValueType ValueType { get; set; }
    public string Text
    {
      get
      {
        if (text == null) return String.Empty;
        return text;
      }
      set
      {
        if (text != value)
        {
          text = value;
          OnPropertyChanged("Text");
        }
      }
    }
    public bool isValidData = true;
    public bool IsValidData
    {
      get { return isValidData; }
      set
      {
        if (isValidData != value)
        {
          isValidData = value;
          OnPropertyChanged("IsValidData");
        }
      }
    }
    public string ErrorMessage { get; set; }
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string info)
    {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null)
      {
        handler(this, new PropertyChangedEventArgs(info));
      }
    }
  }

  public class StringValue : MySubKeyValue
  {
    public StringValue(string str = null)
    {
      ValueType = MySubKeyValueType.StringValue;
      Text = str;
    }
  }
  public class ListValue : MySubKeyValue 
  {
    private int index;
    public int Index
    {
      get { return index; }
      set
      {
        index = value;
        if (index > -1 && index < valueEntityList.Count)
        {
          base.Text = valueEntityList[index];
          IsValidData = true;
        }
        else
          IsValidData = false;
        OnPropertyChanged("Index");
      }
    }

    public List<string> valueEntityList { get; set; }
    public List<string> viewEntityList { get; set; }
    public ListValue(string str, ListValue l)
    {
      ValueType = MySubKeyValueType.ListValue;
      valueEntityList = l.valueEntityList;
      viewEntityList = l.viewEntityList;
      base.Text = str;
      Index = valueEntityList.FindIndex(v => v == str);
    }
    public ListValue(List<string> _vals = null, List<string> _views = null, string str = "")
    {
      Index = -1;
      ValueType = MySubKeyValueType.ListValue;
      valueEntityList = new List<string>();
      viewEntityList = new List<string>();
      if (_vals != null)
        if (_views != null && _views.Count == _vals.Count)
        {
          valueEntityList.AddRange(_vals);
          viewEntityList.AddRange(_views);
        }
        else
        {
          valueEntityList.AddRange(_vals);
          viewEntityList.AddRange(_vals);
        }
      base.Text = str;
      Index = valueEntityList.FindIndex(v => v == str);
    }
  }
  public class ColumnDefinition : INotifyPropertyChanged
  {
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string info)
    {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null)
      {
        handler(this, new PropertyChangedEventArgs(info));
      }
    }
    public ColumnDefinition(string name = "", int width = 80)
    {
      ColumnName = name;
      ColumnWidth = width;
    }
    public string ColumnName { get; set; }
    private int columnWidth;
    public int ColumnWidth
    {
      get { return columnWidth; }
      set { columnWidth = value; OnPropertyChanged("ColumnWidth"); }
    }
  }

}
使用系统;
使用系统组件模型;
使用System.Collections.ObjectModel;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Text.RegularExpressions;
使用System.Collections.Specialized;
使用System.Windows.Data;
使用System.Windows;
使用数据虚拟化;
使用系统线程;
//使用系统线程;
命名空间WpfApplication\u异步
{
公共枚举MySubKeyValueType{StringValue=0,ListValue=1}
公共类MySection:IItemsProvider
{
/// 
///获取可用项目的总数。
/// 
/// 
公共整数FetchCount()
{
//睡眠(1000);
返回记录。计数;
}
/// 
///获取一系列项目。
/// 
///开始索引。
///要获取的项目数。
/// 
公共IList FetchRange(int startIndex,int count)
{
//睡眠(1000);
如果(startIndex>Records.Count)startIndex=Records.Count;
如果(startIndex+count>Records.count)count=Records.count-startIndex;
return Records.ToList().GetRange(startIndex,count).ToList();
}
公共部门()
{
记录=新的ObservableCollection();
}
公共可观察收集记录{get;set;}
}
公共类MyRecord:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
受保护的void OnPropertyChanged(字符串信息)
{
PropertyChangedEventHandler处理程序=PropertyChanged;
if(处理程序!=null)
{
处理程序(此,新属性ChangedEventArgs(信息));
}
}
公共档案()
{
Items=新的ObservableCollection();
}
私钥;
公共字符串密钥{
获取{
返回键;
} 
设置{
//if(Key!=null&&this.Parent为MySection&(this.Parent为MySection.SectionDefinition.IsNumberedKeys)
//返回;
键=值;
已更改的不动产(“密钥”);
} 
}
ObservableCollection items=新的ObservableCollection();
公共可观测收集项目
{
得到{
退货项目;
}
设置{
项目=价值;
OnPropertyChanged(“NumberedColumnText”);
}
} 
}
公共类MySubKeyValue:DependencyObject,INotifyPropertyChanged
{
private ColumnDefinition columnDef=null;
公共列定义列定义
{
得到
{
if(columnDef==null)
return columnDef=new ColumnDefinition();
返回列def;
}
设置{columnDef=value;}
}
public MySubKeyValue(字符串str=null)
{
Text=str;
ValueType=MySubKeyValueType.StringValue;
IsValidData=true;
ErrorMessage=“error”;
}
私有字符串文本;
public MySubKeyValueType ValueType{get;set;}
公共字符串文本
{
得到
{
if(text==null)返回String.Empty;
返回文本;
}
设置
{
如果(文本!=值)
{
文本=值;
OnPropertyChanged(“文本”);
}
}
}
公共bool isValidData=true;
公共布尔伊斯瓦利达酒店
{
获取{return isValidData;}
设置
{
如果(isValidData!=值)
{
isValidData=值;
OnPropertyChanged(“IsValidData”);
}
}
}
公共字符串错误消息{get;set;}
公共事件属性更改事件处理程序属性更改;
受保护的虚拟void OnPropertyChanged(字符串信息)
{
PropertyChangedEventHandler处理程序=PropertyChanged;
if(处理程序!=null)
{
处理程序(此,新属性ChangedEventArgs(信息));
}
}
}
公共类StringValue:MySubKeyValue
{
公共字符串值(字符串str=null)
{
ValueType=MySubKeyValueType.StringValue;
Text=str;
}
}
公共类ListValue:MySubKeyValue
{
私有整数索引;
公共整数索引
{
获取{返回索引;}
设置
{
指数=价值;
如果(索引>-1&&indexv==str);
}
public ListValue(列表_vals=null,列表_views=null,字符串str=”“)
{
指数=-1;
ValueType=MySubKeyValueType.ListValue;
valueEntityList=新列表();
viewEntityList=新列表();
如果(_vals!=null)
如果(_views!=null&&&u views.Count==_vals.Count)
{
valueEntityList.AddRange(\u vals);
viewEntityList.AddRange(_视图);
}
其他的
{
valueEntityList.AddRange(\u vals);
viewEntityList.AddRange(_vals);
}
base.Text=str;
Index=valueEntityList.Fi
namespace WpfApplication_async
{
  public partial class MainWindow : Window
  {
    MySection sec1,sec2;
    bool isSec1 = true;
    public MainWindow()
    {
      InitializeComponent();

      sec1 = new MySection();
      for(int i=0;i<50;i++){
        MyRecord rec = new MyRecord();
        rec.Key = i.ToString();
        for(int j=0;j<20;j++){
          rec.Items.Add(new StringValue("abc"));
          rec.Items[rec.Items.Count - 1].ColumnDef = new ColumnDefinition(j.ToString());
        }
        sec1.Records.Add(rec);
      }
      sec2 = new MySection();
      for (int i = 0; i < 50; i++)
      {
        MyRecord rec = new MyRecord();
        rec.Key = i.ToString();
        for (int j = 0; j < 20; j++)
        {
          rec.Items.Add(new ListValue(new List<string> { "a", "b" }, new List<string> { "a", "b" }, "a"));
          rec.Items[rec.Items.Count - 1].ColumnDef = new ColumnDefinition(j.ToString());
        }
        sec2.Records.Add(rec);
      }
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {

      if (isSec1)
        //listView.DataContext = sec2;
        listView.DataContext = new AsyncVirtualizingCollection<MyRecord>(sec2, 10, 30 * 1000);
      else
        //listView.DataContext = sec1;
        listView.DataContext = new AsyncVirtualizingCollection<MyRecord>(sec1, 10, 30 * 1000);
      isSec1 = !isSec1;
    }
  }
}
foreach (var r in sec.Records)
{
    listView.Dispatcher.Invoke((new Action(delegate()
    {
        listView.Items.Add(r);
    })), DispatcherPriority.SystemIdle);
}