If I select a TreeListBox item via its IsSelected property before I expand the RootItem phantom items are created in the TreeListBox. Here's a simple example which shows the issue. To reproduce launch the app and hit the button before expanding anything in the TreeListBox - that will select an item in the tree. If you then expand the items on the left a few phantom entries will be displayed
<Window x:Class="ActiProTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ActiProTest"
xmlns:ac="http://schemas.actiprosoftware.com/winfx/xaml/grids"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<DockPanel LastChildFill="True">
<ac:TreeListBox
SelectionMode="Extended"
MultiSelectionKind="SameDepth"
IsRootItemVisible="True"
Width="200"
DockPanel.Dock="Left"
x:Name="_tree">
<ac:TreeListBox.ItemAdapter>
<local:LayerAdapter/>
</ac:TreeListBox.ItemAdapter>
<ac:TreeListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ac:TreeListBox.ItemTemplate>
</ac:TreeListBox>
<Button Click="Button_Click">hit me</Button>
</DockPanel>
</Window>
using ActiproSoftware.Windows.Controls.Grids;
using System.Collections;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
namespace ActiProTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
MyItem ItemToSelect;
public MainWindow()
{
InitializeComponent();
MyItem root = new MyItem() { Name = "The Root" };
for( int ix = 0; ix < 5; ix++)
{
var subItem = new MyItem() { Name = $"child {ix + 1}" };
for(int iy = 0; iy < 5; iy++)
{
var subsub = new MyItem() { Name = $"sub {ix + 1} {iy + 1}" };
if (ix == 2 && iy == 3) ItemToSelect = subsub;
subItem.Children.Add(subsub);
}
root.Children.Add(subItem);
}
_tree.RootItem = root;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
ItemToSelect.IsSelected = true;
}
}
public class MyItem : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
bool _IsSelected;
public bool IsSelected
{
get { return _IsSelected; }
set
{
if ( value != _IsSelected)
{
_IsSelected = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsSelected"));
}
}
}
ObservableCollection<MyItem> _Children = new ObservableCollection<MyItem>();
public ObservableCollection<MyItem> Children
{
get { return _Children; }
}
public string Name { get; set; }
}
public class LayerAdapter : TreeListBoxItemAdapter
{
public LayerAdapter()
{
IsSelectedPath = "IsSelected";
}
public override IEnumerable GetChildren(TreeListBox ownerControl, object item)
{
return (item as MyItem).Children;
}
public override bool GetIsSelected(TreeListBox ownerControl, object item)
{
return (item as MyItem).IsSelected;
}
public override void SetIsSelected(TreeListBox ownerControl, object item, bool value)
{
(item as MyItem).IsSelected = value;
}
public override bool CanHaveChildren(TreeListBox ownerControl, object item)
{
return (item as MyItem).Children.Count > 0;
}
}
}
[Modified 4 years ago]