/
BindableExpandingBehavior.cs
118 lines (100 loc) · 4.65 KB
/
BindableExpandingBehavior.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
using DevExpress.Mvvm.UI.Interactivity;
using DevExpress.Xpf.Grid;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Windows;
namespace DevExpress.Example04 {
public class BindableExpandingBehavior : Behavior<GridControl> {
public string ExpandingProperty {
get { return (string)GetValue(ExpnaderProperty); }
set { SetValue(ExpnaderProperty, value); }
}
public static readonly DependencyProperty ExpnaderProperty =
DependencyProperty.Register("ExpandingProperty", typeof(string), typeof(BindableExpandingBehavior), new PropertyMetadata(string.Empty));
protected override void OnAttached() {
base.OnAttached();
this.AssociatedObject.Loaded += GridLoaded;
}
protected void AttachItems(TreeListNodeCollection nodes) {
TreeListNodeIterator iterator = new TreeListNodeIterator(nodes);
while(iterator.MoveNext()) {
this.SubscribeObject(iterator.Current.Content);
if(iterator.Current.HasChildren) {
this.AttachItems(iterator.Current.Nodes);
}
}
}
protected void GridLoaded(object sender, RoutedEventArgs e) {
if(!(this.AssociatedObject.View is TreeListView)) {
return;
}
var grid = this.AssociatedObject;
this.AttachItems((grid.View as TreeListView).Nodes);
INotifyCollectionChanged collection = (INotifyCollectionChanged)grid.ItemsSource;
if(collection != null) {
collection.CollectionChanged += collection_CollectionChanged;
}
var tree = (this.AssociatedObject.View as TreeListView);
tree.NodeExpanded += GridNodeChanged;
tree.NodeCollapsed += GridNodeChanged;
}
protected void SubscribeObject(object item) {
var iPropChanged = (INotifyPropertyChanged)item;
if(iPropChanged != null) {
iPropChanged.PropertyChanged += this.PropertyChanged;
}
}
void collection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
switch(e.Action) {
case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
case System.Collections.Specialized.NotifyCollectionChangedAction.Replace:
foreach(var item in e.NewItems) {
this.SubscribeObject(item);
var node = this.FindNodeByValue(item, (this.AssociatedObject.View as TreeListView).Nodes);
if(node != null) {
this.AttachItems(node.Nodes);
}
}
break;
default:
break;
}
}
protected TreeListNode FindNodeByValue(object obj, TreeListNodeCollection nodes) {
TreeListNode result = null;
TreeListNodeIterator iterator = new TreeListNodeIterator(nodes);
while(iterator.MoveNext() && result == null) {
if(iterator.Current.Content == obj) {
result = iterator.Current;
}
if(result == null && iterator.Current.HasChildren) {
result = this.FindNodeByValue(obj, iterator.Current.Nodes);
}
}
return result;
}
public void PropertyChanged(object obj, PropertyChangedEventArgs args) {
if(args.PropertyName == this.ExpandingProperty) {
var treeView = this.AssociatedObject.View as TreeListView;
var node = this.FindNodeByValue(obj, treeView.Nodes);
if(node != null) {
int rowHandle = node.RowHandle;
bool isExpanded = (bool)obj.GetType().GetProperty(args.PropertyName).GetValue(obj, null);
if(this.AssociatedObject.IsValidRowHandle(rowHandle)) {
node.IsExpanded = isExpanded;
}
while(isExpanded && node.ParentNode != null) {
node.ParentNode.IsExpanded = isExpanded;
node = node.ParentNode;
}
}
}
}
void GridNodeChanged(object sender, Xpf.Grid.TreeList.TreeListNodeEventArgs e) {
var propInfo = e.Node.Content.GetType().GetProperty(this.ExpandingProperty);
if(propInfo != null) {
propInfo.SetValue(e.Node.Content, e.Node.IsExpanded, null);
}
}
}
}