【问题标题】:How can I make a WPF TreeView data binding lazy and asynchronous?如何使 WPF TreeView 数据绑定变得惰性和异步?
【发布时间】:2010-06-01 15:24:49
【问题描述】:

我正在学习如何在 WPF 中为 TreeView 使用数据绑定。我在程序上创建Binding 对象,设置SourcePathConverter 属性指向我自己的类。我什至可以设置IsAsync,当我探索树时,我可以看到 GUI 异步更新。到目前为止一切顺利!

我的问题是 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 方式”的精神)。

【问题讨论】:

  • 你能描绘出你的树形结构吗?多少级?项目和子项目是否属于同一类型?

标签: wpf data-binding asynchronous lazy-evaluation


【解决方案1】:

一个通用的解决方案(因为我不确定你的代码是不是模拟的)

  1. 创建包含父级和子级的模型(在这种情况下,它是一个 int 和一个 int 列表)
  2. 创建一个 ViewModel,除了 Model 的属性外,还具有 IsExpanded 属性
  3. 将 IsExpanded 属性绑定到视图 (xaml) 中 TreeViewItem 的 IsExpanded 属性
  4. 在 IsExpanded 属性的设置器中,使用 Dispatcher 填写您的 Children 列表,优先级为 Background。每次向子列表中添加项目都应触发 PropertyChanged 事件。

如果您不熟悉,请查看MVVM design pattern。这是good video by Jason

【讨论】:

  • 这是一个很棒的视频。我会等到我消化了内容并得到一个可以工作的应用程序后才会接受答案。
  • 该视频展示了如何在模型层执行后台工作时将事物异步填充到视图层。
  • 我的解决方案是使用 MVVM 模型进行异步更新,如您链接的视频中所做的那样。这结合了一些用于“IsExpanded”的 ModelView 绑定来触发后台工作,一切都很好。 :)
  • @Amsakanna,当您使用 HierarchicalDataTemplate 时可以这样做吗?我很难弄清楚如何创建从自动生成的 TreeViewItem 到 HierarchicalDataTemplate 的 ViewModel 的绑定。
  • @Greg 你知道吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-12
  • 2018-03-20
  • 2010-09-19
  • 1970-01-01
  • 2022-09-30
  • 1970-01-01
  • 2013-02-22
相关资源
最近更新 更多