我有以下问题。我的树视图中有一些项目位于层次结构的顶部。当我单击某个项目以展开它时,事件需要5秒钟才能加载所选节点中的所有项目。如何在此过程中显示“请稍候......扩展节点...”消息?如何确定项目是否仍在扩展或现在是否已加载和显示所有嵌套项目?
我已经在这里提出了非常相似的问题Show "Please wait.." message when expanding TreeView in WPF,我甚至将答案标记为已被接受但是,我现在的解决方案并不令人满意,因为“请等待......”对话框闪烁(显示并关闭)和嵌套项目的数量一样多。)
答案 0 :(得分:1)
正如我在你的帖子评论中提到的那样,我们需要解决两个问题。
WPF不提供BeforeExpand事件,因此您应该使用视图数据,更改属性的通知,数据绑定和可观察集合。我将在简单的应用程序中说明这一点。
整个方法可以大致描述为:
我设计了我的树项ViewData类,其中包含可观察的属性IsExpanded,IsLoaded,可观察的子项集合以及将显示的名称:
public class TreeItem : ObservableObject
{
public TreeItem (string name)
{
this.Name = name;
}
public string Name
{
get;
private set;
}
private bool _isExpanded;
public bool IsExpanded
{
get
{
return this._isExpanded;
}
set
{
if (this._isExpanded != value)
{
this._isExpanded = value;
this.OnPropertyChanged("IsExpanded");
}
}
}
private bool _isLoading;
public bool IsLoading
{
get
{
return this._isLoading;
}
set
{
if (this._isLoading != value)
{
this._isLoading = value;
this.OnPropertyChanged("IsLoading");
}
}
}
private ObservableCollection<TreeItem> _innerItems = new ObservableCollection<TreeItem>();
public IEnumerable<TreeItem> InnerItems
{
get
{
return this._innerItems;
}
}
public void LoadInnerItems()
{
this.IsLoading = true;
var sc= SynchronizationContext.Current;
new Thread(new ThreadStart(() =>
{
Thread.Sleep(5000);
sc.Send(o =>
{
this._innerItems.Add(new TreeItem("1223"));
this._innerItems.Add(new TreeItem("2345"));
this._innerItems.Add(new TreeItem("666678"));
this.IsLoading = false;
}, null);
}))
.Start();
}
}
下一步是开发Presentation Model。如您所见,我们的模型侦听IsExpanded PropertyChanged事件,当它等于true时,启动LoadingInnerItems。:
public class SampleModel : ObservableObject
{
public SampleModel()
{
this._items.Add(new TreeItem("AAA"));
this._items.Add(new TreeItem("BBB"));
this._items.Add(new TreeItem("CCC"));
foreach (var i in this._items)
{
i.PropertyChanged += new PropertyChangedEventHandler(Item_PropertyChanged);
}
}
void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "IsExpanded")
{
var item = (TreeItem)sender;
if(item.IsExpanded)
{
item.LoadInnerItems();
}
}
}
private ObservableCollection<TreeItem> _items = new ObservableCollection<TreeItem>();
public IEnumerable<TreeItem> Items
{
get
{
return this._items;
}
}
}
我们的TreeView的XAML。当我们加载内部项目时 - 我们的treeviewitem的前景变为红色:
<TreeView ItemsSource="{Binding Items}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding InnerItems}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded"
Value="{Binding IsExpanded, Mode=TwoWay}"/>
<Setter Property="Foreground"
Value="Aqua"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsLoading}"
Value="True">
<Setter Property="Foreground"
Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
并且不要忘记在后面的代码中将模型设置为视图的datacontext:
public MainWindow()
{
InitializeComponent();
this.Model = new SampleModel();
}