我需要一个TreeView
来表示存储在SQL Server CE数据库中的多个表的一些分层数据。之前,数据存储在xml中,在启动时很简单的反序列化,一切都很好。现在我被要求将数据移动到数据库,并且遇到了几个问题。如何在延迟加载的WPF MVVM TreeView中搜索?
我的第一个问题是,从数据库中检索多个项目并从这些项目构建一个TreeView ViewModel需要相当长的时间(仍然不确定什么是更长的时间 - 获取项目或构建此树)。所以我实现了延迟加载,现在只有在TreeViewItem
正在扩展时我才会收到项目。
现在,我需要对所有节点执行文本搜索,但要使其工作,必须加载所有节点。 我试图加载所有这些,但树加载时UI冻结。在BackgroundWorker
内部执行此操作对我来说也是不可能的,因为这些项目存储在ObservableCollection
中,我得到“InvalidOperationException”。使用Dispatcher
有助于此,但它也冻结UI ...
从我的TreeViewItem
虚拟机的摘录如下,如果需要更多的代码,请让我知道。也许我对我的设计完全错误,所以任何意见都非常感谢!
public class TreeViewItemViewModel: DisplayableItem, IItemsHost
{
internal static DummyTreeViewItemViewModel _dummy = new DummyTreeViewItemViewModel();
public TreeViewItemViewModel(){}
public TreeViewItemViewModel(IDisplayableItem displayableItem)
{
Data = displayableItem;
}
public TreeViewItemViewModel(IDisplayableItem displayableItem, IDisplayableItem parent)
:this(displayableItem)
{
Parent = parent as TreeViewItemViewModel;
}
private TreeViewItemViewModel _parent;
public TreeViewItemViewModel Parent
{
get { return _parent; }
set { _parent = value; InvokePropertyChanged(new PropertyChangedEventArgs("Parent")); }
}
private IDisplayableItem _data;
public new IDisplayableItem Data
{
get { return _data; }
set { _data = value; InvokePropertyChanged(new PropertyChangedEventArgs("Data")); }
}
private bool _isSelected;
public new bool IsSelected
{
get { return _isSelected; }
set { _isSelected = value; InvokePropertyChanged(new PropertyChangedEventArgs("IsSelected")); }
}
private bool _isEnabled=true;
public new bool IsEnabled
{
get { return _isEnabled; }
set { _isEnabled = value; InvokePropertyChanged(new PropertyChangedEventArgs("IsEnabled")); }
}
private bool _isVisible = true;
public new bool IsVisible
{
get { return _isVisible; }
set { _isVisible = value; InvokePropertyChanged(new PropertyChangedEventArgs("IsVisible")); }
}
private void FillItems()
{
if (Items.Contains(_dummy))
{
Items.Remove(_dummy);
var itemshost = Data as IItemsHost;
if (itemshost != null)
{
_items = new ObservableCollection<IDisplayableItem>();
foreach (var item in itemshost.Items)//getting 'Items' actually requesting them from a database
{
var treeItem = new TreeViewItemViewModel(item, this);
_items.Add(treeItem);
}
InvokePropertyChanged(new PropertyChangedEventArgs("Items"));
}
}
}
protected bool _isExpanded;
public bool IsExpanded
{
get { return _isExpanded; }
set
{
if(value)
{
FillItems();
}
_isExpanded = value;
InvokePropertyChanged(new PropertyChangedEventArgs("IsExpanded"));
}
}
protected SObservableCollection<IDisplayableItem> _items = new SObservableCollection<IDisplayableItem>();
public SObservableCollection<IDisplayableItem> Items
{
get
{
var itemshost = Data as IItemsHost;
if (itemshost != null)
{
if (_items.Count == 0 && itemshost.Items.Count > 0)
_items.Add(_dummy);
}
return _items;
}
set { _items = value; InvokePropertyChanged(new PropertyChangedEventArgs("Items")); }
}
更新:对于那些谁也寻找一个类似的解决方案 - 我的问题是在我的查询方法。每当我需要执行查询时,我都不应该打开新的SQL Server CE连接...
我已经使用'System.Diagnostics.Stopwatch'做了一个简单的测试,发现即使不使用视图(在控制台应用程序中),迭代所有树项目和子项目需要大约30秒,并填充它们全部。这不好,但我不知道该怎么做这:( – lena 2015-02-12 07:25:34