-
Notifications
You must be signed in to change notification settings - Fork 2
/
OptionTree.cs
147 lines (121 loc) · 3.57 KB
/
OptionTree.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace SubwordNavigation
{
class RadioButtonConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
return value.Equals(parameter);
}
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
return (bool)value ? parameter : DependencyProperty.UnsetValue;
}
public static readonly RadioButtonConverter Instance =
new RadioButtonConverter();
}
class OptionTree : TreeView
{
public OptionTree()
{
DataContextChanged += HandleDataContextChanged;
}
void HandleDataContextChanged(object sender,
DependencyPropertyChangedEventArgs e)
{
Items.Clear();
object options = e.NewValue;
Type optionsType = options.GetType();
var categories = new Dictionary<string, TreeViewItem>();
foreach (var property in optionsType.GetProperties(
BindingFlags.Public | BindingFlags.Instance))
{
Control control = null;
Type propertyType = property.PropertyType;
string propertyName = GetName(property);
if (propertyType == typeof(bool))
{
CheckBox checkBox = new CheckBox();
checkBox.Content = propertyName;
checkBox.Focusable = false;
var binding = new Binding(property.Name);
binding.Source = options;
binding.Mode = BindingMode.TwoWay;
checkBox.SetBinding(CheckBox.IsCheckedProperty, binding);
control = checkBox;
}
else if (propertyType.IsEnum)
{
TreeViewItem enumItemsControl = new TreeViewItem();
enumItemsControl.Header = propertyName;
enumItemsControl.Focusable = false;
enumItemsControl.IsExpanded = true;
foreach (var enumerator in propertyType
.GetFields(BindingFlags.Public | BindingFlags.Static))
{
var radioButton = new RadioButton();
radioButton.Content = GetName(enumerator);
radioButton.Focusable = false;
var binding = new Binding(property.Name);
binding.Source = options;
binding.Converter = RadioButtonConverter.Instance;
binding.ConverterParameter = enumerator.GetValue(null);
binding.Mode = BindingMode.TwoWay;
radioButton.SetBinding(RadioButton.IsCheckedProperty, binding);
enumItemsControl.Items.Add(radioButton);
}
control = enumItemsControl;
}
else continue;
var categoryAttribute = property
.GetCustomAttribute<CategoryAttribute>();
if (categoryAttribute != null)
{
string category = categoryAttribute.Category;
TreeViewItem itemsControl;
if (!categories.TryGetValue(category, out itemsControl))
{
itemsControl = new TreeViewItem();
itemsControl.Header = category;
itemsControl.Focusable = false;
itemsControl.IsExpanded = true;
categories.Add(category, itemsControl);
Items.Add(itemsControl);
}
itemsControl.Items.Add(control);
}
else
{
Items.Add(control);
}
}
}
static string GetName(MemberInfo member)
{
var displayNameAttribute = member
.GetCustomAttribute<DisplayNameAttribute>();
if (displayNameAttribute != null)
{
return displayNameAttribute.DisplayName;
}
else
{
var descriptionAttribute = member
.GetCustomAttribute<DescriptionAttribute>();
if (descriptionAttribute != null)
{
return descriptionAttribute.Description;
}
}
return member.Name;
}
}
}