wpf - 如何使 WPF TreeView 数据绑定(bind)惰性和异步?

标签 wpf data-binding asynchronous lazy-evaluation

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

我的问题是 WPF 在 GUI 中扩展之前急切地评估树的部分。如果留下足够长的时间,这将导致整个树被评估(实际上在这个例子中我的树是无限的,但你明白了)。 我希望仅在用户扩展节点时按需评估树。使用 WPF 中现有的异步数据绑定(bind)是否可行?

顺便说一句,我还没有弄清楚 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 事件处理程序并在事件处理程序被触发时直接添加项目来设法对树节点进行惰性计算。我正试图摆脱它并改用数据绑定(bind)(我理解这更符合“WPF 方式”的精神)。

最佳答案

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

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

查看 MVVM design pattern ,如果你不熟悉。这是一个good video by Jason

关于wpf - 如何使 WPF TreeView 数据绑定(bind)惰性和异步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2951015/

相关文章:

android - Parcelable遇到IOException写入可序列化对象引起java.io.NotSerializableException : retrofit2. Retrofit$1

c# - 我可以将 RangeSlider(来自 WPF 扩展工具包)绑定(bind)到 ObservableCollection 的日期时间属性吗?

c# - 将状态更新从 C++ 中的函数发送到 C#

c# - 带有滑入效果的WPF切换桌面

WPF ListBox ItemsSource StaticResource/Binding 问题

asp.net - 无法从数据库中检索所需的数据

Kotlin:有没有工具可以让我在执行挂起函数时控制并行度?

.net - 我应该如何访问 ViewModel 的底层实体/模型

c# - 为所有用户部署 VSTO 加载项

c# - 如何在线程或任务中进行异步操作