У меня есть TreeView в моем View, который привязан к списку корневых Node
s в моей ViewModel.У этих корней Node
s может быть ребенок Nodes
.Все узлы относятся к одному типу и имеют свойство IsSelected
, которое связано со свойством IsChecked
зависимости CheckBox
, которое содержится в соответствующем TreeViewItem
.Для CheckBox
установлено IsThreeState
в false
.
public class Node : PropertyChangedBase, INode
{
private bool? _isSelected;
private IList<INode> _nodes;
private INode _parent;
public Node()
{ }
public bool? IsSelected
{
get { return _isSelected; }
set
{
if (_SetField(ref _isSelected, value))
{
_OnIsSelectedChanged();
}
}
}
public IList<INode> Nodes
{
get { return _nodes; }
set { _SetField(ref _nodes, value); }
}
public INode Parent
{
get { return _parent; }
set { _SetField(ref _parent, value); }
}
private void _OnIsSelectedChanged()
{
if (IsSelected.HasValue)
{
if (IsSelected.Value)
{
if (Parent != null)
{
// Set IsSelected on all parenting nodes to:
// - true, if all of their immediate child packages have been selected
// - null, else
}
if (Nodes != null && Nodes.Count > 0)
{
// Prevent running this method again by circumventing setting the property
_SetField(ref _isSelected, null);
}
}
else
{
if (Parent != null)
{
// Set IsSelected of the parent to null
}
if (Nodes != null)
{
// Set IsSelected = false on all child nodes
}
}
}
else if (Parent != null)
{
// Set IsSelected on all parenting nodes to:
// - true, if all of their immediate child packages have been selected
// - null, else
}
}
}
PropertyChangedBase
- базовый класс, реализующий INotifyPropertyChanged
.Он был разработан после этого SO ответа .Если установленное значение действительно изменяется, _SetField(ref object, object)
возвращает true
и уведомляет об изменении свойства.
Если пользователь щелкает CheckBox, это изменение должно распространяться на родительский узел (до корневого узла) IsSelected
свойство и свойство IsSelected
дочернего узла тоже.После распространения всех свойств я хочу запустить событие.Но только тогда, когда никакие дальнейшие узлы не будут изменены.Затем я хочу сделать что-то во ViewModel, что занимает некоторое время, поэтому было бы плохо с точки зрения производительности, если бы событие запускалось с каждым измененным свойством.
Поведение должно быть следующим:
- Если для
IsSelected
узла установлено значение true
или null
, для IsSelected
родительского узла устанавливается значение null
, если не для всех IsSelected
дочернего элемента узла установлено значение true
или null
(что затем распространяется по дереву). - Если для
IsSelected
узла установлено значение true
или null
, для IsSelected
родительского узла устанавливается значение true
, если всеIsSelected
родного брата узла установлены в true
или null
(что затем распространяется вверх по дереву). - Если
IsSelected
узла получает значение false
, все его непосредственные дочерние элементыIsSelected
узла также устанавливают на false
(что затем распространяется вниз по дереву). - Узел, установленный на
null
, означает, что не все его непосредственные дочерние узлы были выбраны.
Итак, как мне добиться запуска события PropertyChanged (или другого, который я бы реализовал) только в кормовой части?последний узел был изменен?