/// <summary> /// Gets the UiProperty attribute associated with a property. For some reason, PropertyInfo.GetCustomAttributes doesn't return the /// UiProperty attribute placed on abstract properties that are overridden. /// </summary> /// <returns>The user interface property attribute.</returns> /// <param name="property">Property.</param> public static UiProperty GetUiPropertyAttribute(PropertyInfo property) { if (property == null) { return(null); } UiProperty attribute = property.GetCustomAttribute <UiProperty>(); if (attribute == null) { Type parentType = property.ReflectedType.BaseType; if (parentType == null) { return(null); } else { return(GetUiPropertyAttribute(parentType.GetProperty(property.Name))); } } else { return(attribute); } }
/// <summary> /// Gets a list of StackLayout objects associated with properties in an object that have been /// decorated with a UiProperty attribute. /// </summary> /// <returns>The property stacks.</returns> /// <param name="o">Object to get StackLayouts for.</param> public static List <StackLayout> GetPropertyStacks(object o) { List <Tuple <PropertyInfo, UiProperty> > propertyUiElements = o.GetType() .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .Select(p => new Tuple <PropertyInfo, UiProperty>(p, GetUiPropertyAttribute(p))) .Where(p => p.Item2 != null) .OrderBy(p => p.Item2._order).ToList(); List <StackLayout> propertyStacks = new List <StackLayout>(); foreach (Tuple <PropertyInfo, UiProperty> propertyUiElement in propertyUiElements) { PropertyInfo property = propertyUiElement.Item1; UiProperty uiElement = propertyUiElement.Item2; Label propertyLabel = new Label { Text = uiElement.LabelText ?? property.Name + ":", FontSize = 20 }; BindableProperty targetProperty = null; IValueConverter converter = null; View propertyView = uiElement.GetView(property, o, out targetProperty, out converter); propertyView.IsEnabled = uiElement.Editable; #if UNIT_TESTING // set style id so we can get the property value when unit testing propertyView.StyleId = propertyLabel.Text + " View"; #endif if (targetProperty != null) { propertyView.BindingContext = o; propertyView.SetBinding(targetProperty, new Binding(property.Name, converter: converter)); } propertyStacks.Add(new StackLayout { Orientation = StackOrientation.Vertical, VerticalOptions = LayoutOptions.Start, Children = { propertyLabel, propertyView } }); } return(propertyStacks); }