【发布时间】:2015-02-11 12:57:45
【问题描述】:
我需要一个TreeView 来表示存储在 SQL Server CE 数据库中的多个表中的一些分层数据。以前,数据存储在 xml 中,并在启动时进行简单的反序列化,一切都很好。现在我被要求将数据移动到数据库中,我遇到了几个问题。
我的第一个问题是从数据库中检索许多项目并从这些项目构建 TreeView ViewModel 需要很长时间(仍然不确定什么更长 - 获取项目或构建这棵树)。所以我实现了延迟加载,现在我只有在 TreeViewItem 扩展时才能获取项目。
现在,我需要对所有节点执行文本搜索,但要使其工作,必须加载所有节点。
我试图加载所有这些,但 UI 在树加载时冻结。在BackgroundWorker 中执行此操作对我来说也是不可能的,因为这些项目存储在ObservableCollection 中并且我得到“InvalidOperationException”。使用 Dispatcher 有助于解决此问题,但它也会冻结 UI...
我的TreeViewItem VM 的摘录如下,如果需要更多代码,请告诉我。也许我的设计完全错了,所以非常感谢任何 cmet!
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 连接...
【问题讨论】:
标签: wpf mvvm treeview sql-server-ce