4 using System.Collections;
5 using System.Collections.Generic;
6 using System.Reflection;
11 namespace MonoDroid.Dialog
16 Dictionary<Element, MemberAndInstance> mappings;
17 private Context _context;
19 class MemberAndInstance
21 public MemberAndInstance(MemberInfo mi,
object o)
26 public MemberInfo Member;
30 static object GetValue(MemberInfo mi,
object o)
32 var fi = mi as FieldInfo;
34 return fi.GetValue(o);
35 var pi = mi as PropertyInfo;
37 var getMethod = pi.GetGetMethod();
38 return getMethod.Invoke(o,
new object[0]);
41 static void SetValue(MemberInfo mi,
object o,
object val)
43 var fi = mi as FieldInfo;
49 var pi = mi as PropertyInfo;
50 var setMethod = pi.GetSetMethod();
51 setMethod.Invoke(o,
new object[] { val });
54 static string MakeCaption(
string name)
56 var sb =
new StringBuilder(name.Length);
59 foreach (
char c
in name)
63 sb.Append(Char.ToUpper(c));
82 static Type GetTypeForMember(MemberInfo mi)
85 return ((FieldInfo)mi).FieldType;
86 else if (mi is PropertyInfo)
87 return ((PropertyInfo)mi).PropertyType;
91 public BindingContext(Context context,
object callbacks,
object o,
string title)
96 throw new ArgumentNullException(
"o");
98 mappings =
new Dictionary<Element, MemberAndInstance>();
101 Populate(callbacks, o, Root);
104 void Populate(
object callbacks,
object o,
RootElement root)
106 MemberInfo last_radio_index = null;
107 var members = o.GetType().GetMembers(BindingFlags.DeclaredOnly | BindingFlags.Public |
108 BindingFlags.NonPublic | BindingFlags.Instance);
112 foreach (var mi
in members)
114 Type mType = GetTypeForMember(mi);
119 string caption = null;
120 object[] attrs = mi.GetCustomAttributes(
false);
122 foreach (var attr
in attrs)
127 caption = ((CaptionAttribute)attr).Caption;
132 var sa = attr as SectionAttribute;
133 section =
new Section(sa.Caption, sa.Footer);
140 caption = MakeCaption(mi.Name);
143 section =
new Section();
145 Element element = null;
147 if (mType == typeof(
string)) {
148 PasswordAttribute pa = null;
149 AlignmentAttribute align = null;
150 EntryAttribute ea = null;
152 EventHandler invoke = null;
155 foreach (
object attr
in attrs) {
156 if (attr is PasswordAttribute)
157 pa = attr as PasswordAttribute;
158 else if (attr is EntryAttribute)
159 ea = attr as EntryAttribute;
160 else if (attr is MultilineAttribute)
162 else if (attr is HtmlAttribute)
164 else if (attr is AlignmentAttribute)
165 align = attr as AlignmentAttribute;
167 if (attr is OnTapAttribute) {
168 string mname = ((OnTapAttribute)attr).Method;
170 if (callbacks == null) {
171 throw new Exception(
"Your class contains [OnTap] attributes, but you passed a null object for `context' in the constructor");
174 var method = callbacks.GetType().GetMethod(mname);
176 throw new Exception(
"Did not find method " + mname);
178 method.Invoke(method.IsStatic ? null : callbacks,
new object[0]);
183 string value = (string)GetValue(mi, o);
185 element =
new EntryElement(caption, value) { Hint = pa.Placeholder, Password =
true };
187 element =
new EntryElement(caption, value) { Hint = ea.Placeholder };
189 element =
new MultilineElement(caption, value);
190 else if (html != null)
191 element =
new HtmlElement(caption, value);
194 var selement =
new StringElement(caption, value);
198 selement.Alignment = align.Alignment;
206 else if (mType == typeof(
float))
208 var floatElement =
new FloatElement(null, null, (
int)GetValue(mi, o));
209 floatElement.Caption = caption;
210 element = floatElement;
212 foreach (
object attr
in attrs)
214 if (attr is RangeAttribute)
216 var ra = attr as RangeAttribute;
217 floatElement.MinValue = ra.Low;
218 floatElement.MaxValue = ra.High;
219 floatElement.ShowCaption = ra.ShowCaption;
223 else if (mType == typeof(
bool))
225 bool checkbox =
false;
226 foreach (
object attr
in attrs)
228 if (attr is CheckboxAttribute)
233 element =
new CheckboxElement(caption, (
bool)GetValue(mi, o));
235 element =
new BooleanElement(caption, (
bool)GetValue(mi, o));
237 else if (mType == typeof(DateTime))
239 var dateTime = (DateTime)GetValue(mi, o);
240 bool asDate =
false, asTime =
false;
242 foreach (
object attr
in attrs)
244 if (attr is DateAttribute)
246 else if (attr is TimeAttribute)
251 element =
new DateElement(caption, dateTime);
253 element =
new TimeElement(caption, dateTime);
255 element =
new DateTimeElement(caption, dateTime);
257 else if (mType.IsEnum)
259 var csection =
new Section();
260 ulong evalue = Convert.ToUInt64(GetValue(mi, o), null);
264 foreach (var fi
in mType.GetFields(BindingFlags.Public | BindingFlags.Static))
266 ulong v = Convert.ToUInt64(GetValue(fi, null));
271 csection.Add(
new RadioElement(MakeCaption(fi.Name)));
275 element =
new RootElement(caption,
new RadioGroup(null, selected)) { csection };
277 else if (mType == typeof(ImageView))
279 element =
new ImageElement(null);
281 else if (typeof(
System.Collections.IEnumerable).IsAssignableFrom(mType))
283 var csection =
new Section();
286 if (last_radio_index == null)
287 throw new Exception(
"IEnumerable found, but no previous int found");
290 csection.Add(
new RadioElement(e.ToString()));
293 int selected = (int)GetValue(last_radio_index, o);
294 if (selected >= count || selected < 0)
296 element =
new RootElement(caption,
new MemberRadioGroup(null, selected, last_radio_index)) { csection };
297 last_radio_index = null;
299 else if (typeof(
int) == mType)
301 foreach (
object attr
in attrs)
303 if (attr is RadioSelectionAttribute)
305 last_radio_index = mi;
312 var nested = GetValue(mi, o);
315 var newRoot =
new RootElement(caption);
316 Populate(callbacks, nested, newRoot);
324 section.Add(element);
325 mappings[element] =
new MemberAndInstance(mi, o);
330 class MemberRadioGroup : RadioGroup
332 public MemberInfo mi;
334 public MemberRadioGroup(
string key,
int selected, MemberInfo mi)
335 : base(key, selected)
346 protected virtual void Dispose(
bool disposing)
350 foreach (var element
in mappings.Keys)
360 foreach (var dk
in mappings)
363 MemberInfo mi = dk.Value.Member;
364 object obj = dk.Value.Obj;
367 SetValue(mi, obj, ((DateTimeElement)element).DateValue);
369 SetValue(mi, obj, ((FloatElement)element).Value);
371 SetValue(mi, obj, ((BooleanElement)element).Value);
373 SetValue(mi, obj, ((CheckboxElement)element).Value);
376 var entry = (EntryElement)element;
378 SetValue(mi, obj, entry.Value);
381 SetValue(mi, obj, ((ImageElement)element).Value);
384 var re = element as RootElement;
385 if (re._group as MemberRadioGroup != null)
387 var group = re._group as MemberRadioGroup;
388 SetValue(group.mi, obj, re.RadioSelected);
392 var mType = GetTypeForMember(mi);
393 var fi = mType.GetFields(BindingFlags.Public | BindingFlags.Static)[re.RadioSelected];
395 SetValue(mi, obj, fi.GetValue(null));
Used to display toggle button on the screen.
virtual void Dispose(bool disposing)
BindingContext(Context context, object callbacks, object o, string title)
The type of the serialized type will be passed as a generic arguments of the serializer. Example: serializer of A becomes instantiated as Serializer{A}.
Sections contain individual Element instances that are rendered by MonoDroid.Dialog ...
Captures the information about mutually exclusive elements in a RootElement