~briangenisio/mypetproject/Main : /ActiveViewModel/ActiveViewModel.cs (revision 7)

Line Revision Contents
1 2
using System;
2
using System.Collections.Generic;
3
using System.ComponentModel;
4
using System.Linq;
5 3
using System.Reflection;
6
using Microsoft.Practices.Composite.Presentation.Commands;
7 2
8 3
namespace HouseOfBilz
9 2
{
10
    public class ActiveViewModel<PropertyT> : CustomTypeDescriptor, INotifyPropertyChanged
11
    {
12
        private readonly Dictionary<string, object> _values = new Dictionary<string, object>();
13
14
        public ActiveViewModel()
15
        {
16
            if (!typeof(PropertyT).IsEnum) throw new InvalidCastException("ActiveModel<PropertyT>: PropertyT must be an enum");
17 3
            CreateCommands();
18 2
        }
19
20 3
        public object Get(PropertyT name) { return Get(name.ToString()); }
21 2
        public T Get<T>(PropertyT name) { return (T)Get(name); }
22
        public T Get<T>(string name) { return (T)Get(name); }
23
        public object Get(string name)
24
        {
25
            if (_values.ContainsKey(name))
26
                return _values[name];
27
28
            return null;
29
        }
30
31
        protected void Set<T>(PropertyT name, T value) { Set(name.ToString(), value); }
32
        public void Set<T>(string name, T value)
33
        {
34
            if (_values.ContainsKey(name))
35
                _values[name] = value;
36
            else
37
                _values.Add(name, value);
38
39
            FirePropertyChanged(name);
40 5
            FireCanExecuteChanged(name);
41 2
        }
42
43
        protected void FirePropertyChanged(string propertyName)
44
        {
45
            var handlers = PropertyChanged;
46
            if (handlers != null)
47
                handlers(this, new PropertyChangedEventArgs(propertyName));
48
        }
49
50
        public event PropertyChangedEventHandler PropertyChanged;
51
52
        public override PropertyDescriptorCollection GetProperties()
53
        {
54
            return GetProperties(new Attribute[0]);
55
        }
56
57
        public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
58
        {
59
            var result = new PropertyDescriptorCollection(base.GetProperties().Cast<PropertyDescriptor>().ToArray());
60
61 3
            PropertyNames.Union(CommandNames).Each(name => result.Add(new ViewModelProperty(name, attributes)));
62 2
63
            return result;
64
        }
65
66 3
        private const string EXECUTE_PREFIX = "Execute_";
67 4
        private const string CAN_EXECUTE_PREFIX = "CanExecute_";
68 3
69
        private IEnumerable<string> CommandNames
70
        {
71
            get
72
            {
73
                return from method in GetType().GetMethods().Cast<MethodInfo>()
74
                       where method.Name.StartsWith(EXECUTE_PREFIX)
75
                       select method.Name.StripLeft(EXECUTE_PREFIX.Length);
76
            }
77
        }
78
79 5
        private static IEnumerable<string> PropertyNames
80 3
        {
81
            get
82
            {
83
                return from name in Enum.GetValues(typeof(PropertyT)).Cast<PropertyT>()
84
                       select name.ToString();
85
            }
86
        }
87
88
        private void CreateCommands()
89
        {
90 4
            CommandNames.Each(name => Set(name, new DelegateCommand<object>(x => ExecuteCommand(name), x => CanExecuteCommand(name))));
91 3
        }
92
93
        private void ExecuteCommand(string name)
94
        {
95
            var methodInfo = GetType().GetMethod(EXECUTE_PREFIX + name);
96
            if (methodInfo == null) return;
97
98
            methodInfo.Invoke(this, null);
99
        }
100
101 4
        private bool CanExecuteCommand(string name)
102
        {
103
            var methodInfo = GetType().GetMethod(CAN_EXECUTE_PREFIX + name);
104 5
            if (methodInfo == null) return true;
105
106
            return (bool)methodInfo.Invoke(this, null);
107
        }
108
109
        private void FireCanExecuteChanged(string propertyName)
110
        {
111
            CommandsDependentUpon(propertyName)
112
                .Each(commandName => {
113
                    var command = Get<DelegateCommand<object>>(commandName);
114
                    if (command != null)
115
                        command.RaiseCanExecuteChanged();
116
                });
117
118
        }
119
120
        private IEnumerable<string> CommandsDependentUpon(string propertyName)
121
        {
122
            foreach (var name in CommandNames)
123
            {
124
                var methodInfo = GetType().GetMethod(CAN_EXECUTE_PREFIX + name);
125
                if (methodInfo == null) continue;
126
127 7
                var dependentUpon = methodInfo.GetCustomAttributes(typeof(DependentUponAttribute), true).Cast<DependentUponAttribute>()
128
                    .Any(attribute => attribute.Names.Contains(propertyName));
129 5
130
                if (dependentUpon)
131
                    yield return name;
132
            }
133 4
        }
134
135 3
        private class ViewModelProperty : PropertyDescriptor
136
        {
137
            public ViewModelProperty(string name, Attribute[] attributes)
138 2
                : base(name, attributes)
139
            {
140
            }
141
142
            public override object GetValue(object component)
143
            {
144
                var viewModel = component as ActiveViewModel<PropertyT>;
145 3
                if (viewModel == null) return null;
146 2
147
                return viewModel.Get(Name);
148
            }
149
150
            public override void SetValue(object component, object value)
151
            {
152
                var viewModel = component as ActiveViewModel<PropertyT>;
153
                if (viewModel == null) return;
154
155
                viewModel.Set(Name, value);
156
            }
157
158
            public override void ResetValue(object component) { SetValue(component, null); }
159
            public override bool ShouldSerializeValue(object component) { return false; }
160
            public override Type ComponentType { get { return typeof(ActiveViewModel<PropertyT>); } }
161
            public override bool IsReadOnly { get { return false; } }
162
            public override Type PropertyType { get { return typeof(object); } }
163
            public override bool CanResetValue(object component) { return true; }
164
        }
165
    }
166 3
167 5
    [AttributeUsage(AttributeTargets.Method)]
168 7
    public class DependentUponAttribute : Attribute
169 5
    {
170 7
        public DependentUponAttribute(params object[] properties)
171 5
        {
172
            Names = properties.Select(name => name.ToString());
173
        }
174
175
        public IEnumerable<string> Names { get; private set; }
176
    }
177
178 3
    public static class Extensions
179
    {
180
        public static string StripLeft(this string value, int length)
181
        {
182
            return value.Substring(length, value.Length - length);
183
        }
184
185
        public static void Each<T>(this IEnumerable<T> list, Action<T> action)
186
        {
187
            foreach (var item in list)
188
                action(item);
189
        }
190
    }
191 2
}

Loggerhead 1.10 is a web-based interface for Bazaar branches