Children 更改 TreeView 的 ItemsSource 时丢失
Children missing when changing ItemsSource of TreeView
我有多个 ObservableCollections of Items children。我试图将 TreeView 绑定到一个集合,用户将在运行时 select 源代码。用户可以将列表拖放到 reorganise/edit 活动源集合。
只要您从不切换到以前的 selected 源,我所尝试的就可以完美运行。切换回以前的源将导致丢失 children,仅显示根项目。如果 children 在返回之前展开,一些 children 剩余,而另一些则没有,则此行为会变得更加不一致。
xaml:
<Grid RowSpacing="8" Margin="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Name="ShowC1" Click="ShowC1_Click" Content="Container 1"/>
<Button x:Name="ShowC2" Click="ShowC2_Click" Content="Container 2"/>
<Button x:Name="ShowC3" Click="ShowC3_Click" Content="Container 3"/>
</StackPanel>
<muxc:TreeView x:Name="ItemTree" ItemsSource="{x:Bind Source}" Grid.Row="1">
<muxc:TreeView.ItemTemplate>
<DataTemplate x:DataType="local:Item">
<muxc:TreeViewItem ItemsSource="{x:Bind Children}" Content="{x:Bind Name}"/>
</DataTemplate>
</muxc:TreeView.ItemTemplate>
</muxc:TreeView>
</Grid>
xaml.cs
public sealed partial class MainPage : Page
{
private Container _con1, _con2, _con3;
ExtendedObservableCollection<Item> Source = new ExtendedObservableCollection<Item>();
public MainPage()
{
this.InitializeComponent();
_con1 = new Container("Container 1", 2);
_con2 = new Container("Container 2", 3);
_con3 = new Container("Container 3", 4);
}
private void ShowC1_Click(object sender, RoutedEventArgs e)
{
Source.ReplaceAll(_con1.Items);
}
private void ShowC2_Click(object sender, RoutedEventArgs e)
{
Source.ReplaceAll(_con2.Items);
}
private void ShowC3_Click(object sender, RoutedEventArgs e)
{
Source.ReplaceAll(_con3.Items);
}
}
public class Container
{
public string Title { get; set; } = "Untitled";
public ObservableCollection<Item> Items { get; private set; } = new ObservableCollection<Item>();
public Container(string title, int numItems)
{
Title = title;
for (int i = 0; i < numItems; i++)
{
Items.Add(new Item("Item " + i, i + 1));
}
}
}
public class Item
{
public string Name { get; set; } = "Item";
public ObservableCollection<Item> Children { get; set; } = new ObservableCollection<Item>();
public Item(string name, int numChildren)
{
Name = name;
for (int i = 0; i < numChildren; i++)
{
Children.Add(new Item("Child " + i, 0));
}
}
}
ExtendedObservableCollection.cs
public class ExtendedObservableCollection<T> : ObservableCollection<T>
{
public void ReplaceAll(ICollection<T> items)
{
this.Items.Clear();
foreach (T item in items)
{
this.Items.Add(item);
}
this.OnCollectionChanged(
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)
);
}
}
问题动图:
Code result
更新:临时解决方法,直到我找到适合我需要的更好的东西
首先,我注意到该集合甚至没有通过拖放操作进行更新,但引用最新的 WinUI 修复了该问题。我还更改了绑定以使用 x:Bind.
其次,我能够通过清除 TreeView 源、更新绑定、然后设置为虚拟集合(至少有 1 个成员,0 结果为由于某种原因未能仅加载最后一个 children),更新绑定,然后最终将其设置为真实源,并最后一次更新绑定。每次绑定更新之间都需要异步延迟来刷新 TreeView。这样做的缺点是它会在源为空白时引入闪烁帧。
抱歉我迟到的回复。
我们研究了您的问题,此问题已在新版 Microsoft.UI.Xaml (WinUI
2.x). You can check this commit 中得到解决。
WinUI
是微软开源的新一代UI工具框架。由于社区支持,它可以更快地更新。我们建议您使用它提供的 TreeView
控件来完成您的 UI 布局。
此致。
此问题的修复已随 Microsoft.UI.Xaml v2.4.0 一起提供。请参阅此 commit 了解更多信息。
我有多个 ObservableCollections of Items children。我试图将 TreeView 绑定到一个集合,用户将在运行时 select 源代码。用户可以将列表拖放到 reorganise/edit 活动源集合。
只要您从不切换到以前的 selected 源,我所尝试的就可以完美运行。切换回以前的源将导致丢失 children,仅显示根项目。如果 children 在返回之前展开,一些 children 剩余,而另一些则没有,则此行为会变得更加不一致。
xaml:
<Grid RowSpacing="8" Margin="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Name="ShowC1" Click="ShowC1_Click" Content="Container 1"/>
<Button x:Name="ShowC2" Click="ShowC2_Click" Content="Container 2"/>
<Button x:Name="ShowC3" Click="ShowC3_Click" Content="Container 3"/>
</StackPanel>
<muxc:TreeView x:Name="ItemTree" ItemsSource="{x:Bind Source}" Grid.Row="1">
<muxc:TreeView.ItemTemplate>
<DataTemplate x:DataType="local:Item">
<muxc:TreeViewItem ItemsSource="{x:Bind Children}" Content="{x:Bind Name}"/>
</DataTemplate>
</muxc:TreeView.ItemTemplate>
</muxc:TreeView>
</Grid>
xaml.cs
public sealed partial class MainPage : Page
{
private Container _con1, _con2, _con3;
ExtendedObservableCollection<Item> Source = new ExtendedObservableCollection<Item>();
public MainPage()
{
this.InitializeComponent();
_con1 = new Container("Container 1", 2);
_con2 = new Container("Container 2", 3);
_con3 = new Container("Container 3", 4);
}
private void ShowC1_Click(object sender, RoutedEventArgs e)
{
Source.ReplaceAll(_con1.Items);
}
private void ShowC2_Click(object sender, RoutedEventArgs e)
{
Source.ReplaceAll(_con2.Items);
}
private void ShowC3_Click(object sender, RoutedEventArgs e)
{
Source.ReplaceAll(_con3.Items);
}
}
public class Container
{
public string Title { get; set; } = "Untitled";
public ObservableCollection<Item> Items { get; private set; } = new ObservableCollection<Item>();
public Container(string title, int numItems)
{
Title = title;
for (int i = 0; i < numItems; i++)
{
Items.Add(new Item("Item " + i, i + 1));
}
}
}
public class Item
{
public string Name { get; set; } = "Item";
public ObservableCollection<Item> Children { get; set; } = new ObservableCollection<Item>();
public Item(string name, int numChildren)
{
Name = name;
for (int i = 0; i < numChildren; i++)
{
Children.Add(new Item("Child " + i, 0));
}
}
}
ExtendedObservableCollection.cs
public class ExtendedObservableCollection<T> : ObservableCollection<T>
{
public void ReplaceAll(ICollection<T> items)
{
this.Items.Clear();
foreach (T item in items)
{
this.Items.Add(item);
}
this.OnCollectionChanged(
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)
);
}
}
问题动图: Code result
更新:临时解决方法,直到我找到适合我需要的更好的东西
首先,我注意到该集合甚至没有通过拖放操作进行更新,但引用最新的 WinUI 修复了该问题。我还更改了绑定以使用 x:Bind.
其次,我能够通过清除 TreeView 源、更新绑定、然后设置为虚拟集合(至少有 1 个成员,0 结果为由于某种原因未能仅加载最后一个 children),更新绑定,然后最终将其设置为真实源,并最后一次更新绑定。每次绑定更新之间都需要异步延迟来刷新 TreeView。这样做的缺点是它会在源为空白时引入闪烁帧。
抱歉我迟到的回复。
我们研究了您的问题,此问题已在新版 Microsoft.UI.Xaml (WinUI
2.x). You can check this commit 中得到解决。
WinUI
是微软开源的新一代UI工具框架。由于社区支持,它可以更快地更新。我们建议您使用它提供的 TreeView
控件来完成您的 UI 布局。
此致。
此问题的修复已随 Microsoft.UI.Xaml v2.4.0 一起提供。请参阅此 commit 了解更多信息。