/// <summary> /// Gets the <see cref="UiProperty"/> attribute associated with a property. /// </summary> /// <returns>The user interface property attribute.</returns> /// <param name="property">Property.</param> private static UiProperty GetUiPropertyAttribute(PropertyInfo property) { if (property == null) { return(null); } // For some reason, PropertyInfo.GetCustomAttributes doesn't return the UiProperty attribute placed on abstract // properties that are overridden, so we have to navigate the inheritance tree to search for attributes. 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 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 the <see cref="UiProperty"/> attribute associated with a property. /// </summary> /// <returns>The user interface property attribute.</returns> /// <param name="property">Property.</param> private static UiProperty GetUiPropertyAttribute(PropertyInfo property) { if (property == null) { return(null); } // For some reason, PropertyInfo.GetCustomAttributes doesn't return the UiProperty attribute placed on abstract // properties that are overridden, so we have to navigate the inheritance tree to search for attributes. // bzd3y: This is probably due to Inherited not being set to true in the [AttributeUsage] attribute above. The // code below would probably be unnecessary if that was done. I'm not changing anything, but this can be a // reminder of a possible future change. 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); }
/// <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 }; TapGestureRecognizer labelTapRecognizer = new TapGestureRecognizer() { NumberOfTapsRequired = 1 }; labelTapRecognizer.Tapped += (sender, e) => { // https://predictive-technology-laboratory.github.io/sensus/api/Sensus.Probes.PollingProbe.html#Sensus_Probes_PollingProbe_PollingSleepDurationMS Device.OpenUri(new Uri("https://predictive-technology-laboratory.github.io/sensus/api/" + property.DeclaringType + ".html#" + property.DeclaringType.ToString().Replace('.', '_') + "_" + property.Name)); }; propertyLabel.GestureRecognizers.Add(labelTapRecognizer); BindableProperty targetProperty = null; IValueConverter converter = null; View propertyView = uiElement.GetView(property, o, out targetProperty, out converter); propertyView.IsEnabled = uiElement.Editable; #if UI_TESTING // set style id so we can get the property value when UI 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); }
public static bool HasUiProperties(object o) { return(o.GetType() .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .Any(x => UiProperty.GetUiPropertyAttribute(x) != null)); }