【发布时间】:2014-11-28 08:35:00
【问题描述】:
一些函数提供了一个扁平的字符串列表,如下所示:
var list = new List<int>{1,2,3,4};
TreeView 现在想要将此列表转换为具有两个根节点的树(一个用于奇数,一个用于偶数)。这只是一个示例,因为真实场景必须创建一个更加分层的结构。 关键是后端提供了一个平面列表,视图想要将其转换为树。
我们尝试使用 Converter 作为 ItemsSource,但是当它创建一个新结构时,它基本上会破坏与原始列表的绑定(使异步填充变得不可能)。 Explaining why
这是一个小的复制代码:
代码隐藏:
public partial class MainWindow : Window
{
public ObservableCollection<int> TreeViewSource { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
TreeViewSource = new ObservableCollection<int>();
Action filler =() => { Enumerable.Range(0, 100).ToList().ForEach((i) => { Thread.Sleep(20); TreeViewSource.Add(i); }); };
Task.Run(() => filler()); // ASYNC CALL DOES NOT WORK
//filler(); // SYNC CALL DOES WORK
}
}
public class TreeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var sourceCollection = value as ObservableCollection<int>;
var outputCollection = new List<Item>();
var odd = new Item { Text = "not divisible by 2" };
var even = new Item { Text = "divisible by 2" };
even.Children.AddRange(sourceCollection.Where(x => x % 2 == 0).Select(x => new Item { Text = x.ToString() }));
odd.Children.AddRange(sourceCollection.Where(x => x % 2 != 0).Select(x => new Item { Text = x.ToString() }));
outputCollection.Add(odd);
outputCollection.Add(even);
return outputCollection;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class Item
{
public string Text { get; set; }
public List<Item> Children { get; set; }
public Item()
{
Children = new List<Item>();
}
}
Xaml:
<Window x:Class="TreeViewAsync.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TreeViewAsync"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:TreeConverter x:Key="treeConverter"/>
</Window.Resources>
<Grid>
<TreeView Name="treeView"
ItemsSource="{Binding TreeViewSource, Converter={StaticResource treeConverter}}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Item}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Text}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
这个link 说应该在ItemsSource 上使用DataTemplate 而不是Converter。但是由于模板是单独应用于每个项目的,它如何创建完整的树呢?
再次重申:ViewModel 不需要数据是树,因此不提供树结构而仅提供平面列表。为了方便起见,视图希望将其显示为树。 由于 MVVM,我们希望避免视图中的代码隐藏。
【问题讨论】:
-
stackoverflow.com/a/27171720/4112271这个链接对你有帮助吗???
-
启用绑定到异步列表使用 bindingoperations.enablecollectionsynchronization :)
-
@devhedgehog 我添加了你的建议,但它不能解决问题。
-
@AmolBavannavar 这不是意味着在代码隐藏中编写我自己的绑定代码吗? (两者都不需要)
标签: c# wpf tree treeview ivalueconverter