我正在学习如何在WPF中使用数据绑定来实现TreeView。我正在程序化地创建Binding对象,并将Source、Path和Converter属性设置为指向我的自定义类。我甚至可以设置IsAsync,当我浏览树时,我可以异步地看到GUI更新。到目前为止都很好!
我的问题是,WPF会急切地评估GUI中未展开的树的部分。如果长时间不处理,这将导致整个树被评估(实际上,在这个例子中,我的树是无限的,但你明白我的意思)。我希望仅在用户展开节点时按需评估树。使用WPF中现有的异步数据绑定技术,是否可能实现这一点?
另外,我还没有弄清楚ObjectDataProvider与此任务的关系。
我的XAML代码只包含一个TreeView对象,我的C#代码是:
我的问题是,WPF会急切地评估GUI中未展开的树的部分。如果长时间不处理,这将导致整个树被评估(实际上,在这个例子中,我的树是无限的,但你明白我的意思)。我希望仅在用户展开节点时按需评估树。使用WPF中现有的异步数据绑定技术,是否可能实现这一点?
另外,我还没有弄清楚ObjectDataProvider与此任务的关系。
我的XAML代码只包含一个TreeView对象,我的C#代码是:
public partial class Window1 : Window
{
public Window1() {
InitializeComponent();
treeView.Items.Add( CreateItem(2) );
}
static TreeViewItem CreateItem(int number)
{
TreeViewItem item = new TreeViewItem();
item.Header = number;
Binding b = new Binding();
b.Converter = new MyConverter();
b.Source = new MyDataProvider(number);
b.Path = new PropertyPath("Value");
b.IsAsync = true;
item.SetBinding(TreeView.ItemsSourceProperty, b);
return item;
}
class MyDataProvider
{
readonly int m_value;
public MyDataProvider(int value) {
m_value = value;
}
public int[] Value {
get {
// Sleep to mimick a costly operation that should not hang the UI
System.Threading.Thread.Sleep(2000);
System.Diagnostics.Debug.Write(string.Format("Evaluated for {0}\n", m_value));
return new int[] {
m_value * 2,
m_value + 1,
};
}
}
}
class MyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
// Convert the double to an int.
int[] values = (int[])value;
IList<TreeViewItem> result = new List<TreeViewItem>();
foreach (int i in values) {
result.Add(CreateItem(i));
}
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
throw new InvalidOperationException("Not implemented.");
}
}
}
注意:我之前通过添加WPF事件处理程序并在触发事件处理程序时直接添加项来实现树节点的惰性评估。我试图摆脱这种方法,改用数据绑定(我理解这更符合“WPF方式”)。