У меня странная проблема с WPF TreeView в C#. При запуске моего приложения я хочу развернуть и свернуть все узлы из выбранного узла TreeView. Когда я выбираю root узел, свойство IsSelected не обновляется. Когда я вручную раскрываю узел root и нажимаю на дочерний узел, свойство IsSelected обновляется. Проблема в том, что когда я использую контекстное меню, чтобы развернуть и свернуть дочерние узлы на узле root, узел root не раскрывается. Когда я раскрываю узел root после использования контекстного меню, я вижу, что все дочерние узлы были развернуты правильно.
Я много искал в inte rnet, но не смог найти аналогичный вопрос. Кроме того, я прочитал много уроков и инструкций по C# WPF TreeViews. Пока что моя реализация кажется мне правильной, поэтому я не понимаю, почему свойство IsSelected root не устанавливается при нажатии на узел.
Кто-нибудь может мне помочь? Я реализовал TreeView, ViewModel и Model следующим образом. Заранее спасибо
BR
Майкл
<TreeView
Grid.Row="1"
Grid.Column="0"
Margin="5"
ContextMenuOpening="FrameworkElement_OnContextMenuOpening"
ItemsSource="{Binding HierarchialTestObjects}"
SelectedItemChanged="TreeView_OnSelectedItemChanged">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type vm:HierarchialTestObjectViewModel}" ItemsSource="{Binding Childs}">
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Path=Name}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
<TreeView.ContextMenu>
<ContextMenu>
<MenuItem Command="{Binding ExpandAllTreeItemsCommand}" Header="Expand All" />
<MenuItem Command="{Binding CollapseAllTreeItemsCommand}" Header="Collapse All" />
</ContextMenu>
</TreeView.ContextMenu>
namespace mynamespace.subspace.report.data
{
// ... usings removed
public class HierarchialTestObject
{
public string Name { get; set; }
public List<HierarchialTestObject> Childs { get; set; } = new List<HierarchialTestObject>();
public List<string> Path { get; set; } = new List<string>();
public List<string> ParentPath => Path?.AsEnumerable()?.Reverse()?.Skip(1)?.Reverse()?.ToList();
public IHierarchialItem Item { get; set; }
public HierarchialTestObject(IHierarchialItem item)
{
Item = item;
Name = item.ShortDescription;
}
public void SetChilds(IEnumerable<IHierarchialItem> childs)
{
childs.ToList().ForEach(c => Childs?.Add(new HierarchialTestObject(c)));
}
}
}
ViewModel
namespace mynamespace.subspace.report.viewmodel
{
// ... usings removed
public class HierarchialTestObjectViewModel : ViewModelBase
{
public delegate void NotifyTreeItemSelected(HierarchialTestObjectViewModel item);
public event NotifyTreeItemSelected OnTreeItemSelected;
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
if (_isSelected != value)
{
SetProperty(ref _isSelected, value, nameof(IsSelected));
if (value)
{
// this is a hack-ish workaround because i cannot use PRISM or other similar libs
OnTreeItemSelected?.Invoke(this);
}
}
}
}
private bool _isExpanded;
public bool IsExpanded
{
get { return _isExpanded; }
set
{
if (_isExpanded != value)
{
SetProperty(ref _isExpanded, value, nameof(IsExpanded));
RaisePropertyChanged(nameof(IconType));
}
}
}
private string _name;
public string Name
{
get { return _name; }
set
{
if (_name != value)
{
SetProperty(ref _name, value, nameof(Name));
}
}
}
private IHierarchialItem _item;
public IHierarchialItem Item
{
get { return _item; }
set
{
if (_item != value)
{
SetProperty(ref _item, value, nameof(Item));
}
}
}
private List<string> _path;
public List<string> Path
{
get { return _path; }
set
{
if (_path != value)
{
SetProperty(ref _path, value, nameof(Path));
}
}
}
private ObservableCollection<HierarchialTestObjectViewModel> _childs;
public ObservableCollection<HierarchialTestObjectViewModel> Childs
{
get { return _childs; }
set
{
if (_childs != value)
{
SetProperty(ref _childs, value, nameof(Childs));
}
}
}
public HierarchialTestObjectViewModel(HierarchialTestObject obj)
{
var childs = obj.Childs.Select(c => new HierarchialTestObjectViewModel(c)).ToList();
Path = obj.Path ?? new List<string>();
Childs = new ObservableCollection<HierarchialTestObjectViewModel>(childs);
Item = obj.Item;
Name = obj.Name;
}
public void ExpandRecursively()
{
IsExpanded = true;
Childs?.ToList().ForEach(c => c.ExpandRecursively());
}
public void CollapseRecursively()
{
IsExpanded = false;
Childs?.ToList().ForEach(c => c.CollapseRecursively());
}
}
}