/// <summary> /// Extract all properties from this set of types that have been annotated with an /// AutoUIAttribute, sorted by their order. /// </summary> /// <param name="type"></param> /// <returns></returns> public static IList <PropertyInfo> GetAutoUIProperties(this IEnumerable <Type> types, bool allowDuplicateNames = false) { HashSet <string> names = new HashSet <string>(); SortedList <double, PropertyInfo> result = new SortedList <double, PropertyInfo>(); foreach (Type type in types) { PropertyInfo[] pInfos = type.GetProperties(); foreach (PropertyInfo pInfo in pInfos) { object[] attributes = pInfo.GetCustomAttributes(typeof(AutoUIAttribute), true); if (attributes.Count() > 0 && (allowDuplicateNames || !names.Contains(pInfo.Name))) { AutoUIAttribute aInput = (AutoUIAttribute)attributes[0]; double keyValue = aInput.Order; while (result.ContainsKey(keyValue)) { keyValue = keyValue.NextValidValue(); } result.Add(keyValue, pInfo); names.Add(pInfo.Name); } } } return(result.Values.ToList()); }
/// <summary> /// Extract all methods from this type that have been annotated with an AutoUIAttribute, /// sorted by their order. /// </summary> /// <param name="type"></param> /// <returns></returns> public static IList <MethodInfo> GetAutoUIMethods(this Type type) { SortedList <double, MethodInfo> result = new SortedList <double, MethodInfo>(); MethodInfo[] mInfos = type.GetMethods(); foreach (MethodInfo mInfo in mInfos) { object[] attributes = mInfo.GetCustomAttributes(typeof(AutoUIAttribute), true); if (attributes.Count() > 0) { AutoUIAttribute aInput = (AutoUIAttribute)attributes[0]; double keyValue = aInput.Order; while (result.ContainsKey(keyValue)) { keyValue = keyValue.NextValidValue(); } result.Add(keyValue, mInfo); } } return(result.Values.ToList()); }
/// <summary> /// Set up this control to display the specified object property /// </summary> /// <param name="property"></param> public virtual void AdaptTo(PropertyInfo property) { AutoUIAttribute autoAtt = property.GetCustomAttribute <AutoUIAttribute>(); // Use attribute-defined label if present: if (autoAtt != null && !string.IsNullOrWhiteSpace(autoAtt.Label)) { Label = autoAtt.Label; } // Otherwise, use property name: else { Label = property.Name.AutoSpace(); } // Label binding: if (!string.IsNullOrWhiteSpace(autoAtt?.LabelBinding)) { var bind = new Binding(autoAtt?.LabelBinding); //bind.FallbackValue = Label; SetBinding(LabelProperty, bind); } // Visibility if (!string.IsNullOrWhiteSpace(autoAtt?.VisibilityBinding)) { var vB = new Binding(autoAtt.VisibilityBinding); vB.Converter = new Converters.VisibilityConverter(); SetBinding(VisibilityProperty, vB); } // Tooltip if (!string.IsNullOrWhiteSpace(autoAtt?.ToolTip)) { ToolTip = autoAtt.ToolTip; } }
protected void GenerateAutoUIColumns(IList <PropertyInfo> properties) { Columns.Clear(); // Clear previous columns // TODO: Keep manually-added columns? Model.Model model = null; if (ItemsSource != null && ItemsSource is IOwned <Model.Model> ) { model = ((IOwned <Model.Model>)ItemsSource).Owner; } foreach (PropertyInfo p in properties) { PropertyInfo property = p; Binding binding = null; AutoUIAttribute aUI = property.GetCustomAttribute <AutoUIAttribute>(); if (aUI.SubProperty != null) { // Switch to displaying sub-property binding = new Binding(property.Name + "." + aUI.SubProperty); property = property.PropertyType.GetProperty(aUI.SubProperty); aUI = property.GetCustomAttribute <AutoUIAttribute>(); } else { binding = new Binding(property.Name); } binding.Converter = new TextConverter(model); if (!property.CanWrite) { binding.Mode = BindingMode.OneWay; } DataGridColumn column; if (property.HasAttribute(typeof(AutoUIComboBoxAttribute))) { AutoUIComboBoxAttribute cBA = property.GetCustomAttribute <AutoUIComboBoxAttribute>(); /*var comboColumn = new DataGridComboBoxColumn(); * column = comboColumn; * comboColumn.SelectedItemBinding = binding;*/ /*BindingOperations.SetBinding(comboColumn, DataGridComboBoxColumn.ItemsSourceProperty, * sourceBinding);*/ var comboColumn = new DataGridTemplateColumn(); column = comboColumn; var cellTemplate = new DataTemplate(); var tbFactory = new FrameworkElementFactory(typeof(TextBlock)); tbFactory.SetBinding(TextBlock.TextProperty, binding); //tbFactory.SetValue(TextBlock.PaddingProperty, new Thickness(2.0,2.0,2.0,2.0)); cellTemplate.VisualTree = tbFactory; comboColumn.CellTemplate = cellTemplate; var editTemplate = new DataTemplate(); var cbFactory = new FrameworkElementFactory(typeof(ComboBox)); cbFactory.SetValue(ComboBox.IsTextSearchEnabledProperty, true); cbFactory.SetValue(ComboBox.IsEditableProperty, true); cbFactory.SetValue(ComboBox.PaddingProperty, new Thickness(2.0, 0.0, 2.0, 0.0)); //cbFactory.SetBinding(ComboBox.TextProperty, binding); // Set ItemsSource binding: Binding sourceBinding; if (!string.IsNullOrEmpty(cBA.ItemsSource)) { sourceBinding = new Binding(); sourceBinding.Path = new PropertyPath(cBA.ItemsSource); } else { sourceBinding = new Binding(); if (property.PropertyType.IsEnum) { sourceBinding.Source = Enum.GetValues(property.PropertyType); } else if (typeof(Family).IsAssignableFrom(property.PropertyType)) { sourceBinding.Path = new PropertyPath("Model.Families"); } else if (typeof(CoordinateSystemReference).IsAssignableFrom(property.PropertyType)) { // TEMP: Should be updated to include custom coordinate systems! var pInfo = typeof(CoordinateSystemReference).GetProperty("StandardValues"); sourceBinding.Path = new PropertyPath("(0)", pInfo); //cbFactory.SetValue(ComboBox.ItemsSourceProperty, CoordinateSystemReference.StandardValues); } //sourceBinding.Converter = new ModelTableConverter(); //sourceBinding.ConverterParameter = property.PropertyType; } cbFactory.SetBinding(ComboBox.SelectedItemProperty, new Binding(property.Name)); cbFactory.SetBinding(ComboBox.ItemsSourceProperty, sourceBinding); editTemplate.VisualTree = cbFactory; comboColumn.CellEditingTemplate = editTemplate; } else { var textColumn = new DataGridTextColumn(); column = textColumn; textColumn.Binding = binding; } if (aUI?.Label != null) { column.Header = aUI.Label; } else { column.Header = p.Name.AutoSpace(); } column.MinWidth = 100; Columns.Add(column); } }
/// <summary> /// Populate this UIElementCollection with automatically generated controls for the specified list of members. /// Annotate the properties with the AutoUIAttribute to control how this is done. /// </summary> /// <param name="members"></param> public static void GenerateControlsFor(this UIElementCollection collection, object source, IList <MemberInfo> members) { foreach (MemberInfo member in members) { if (member is PropertyInfo) { // Properties PropertyInfo property = (PropertyInfo)member; FieldControl control = null; Type pType = property.PropertyType; if (property.HasAttribute(typeof(AutoUIComboBoxAttribute))) // Combo box attributes { control = new ComboFieldControl(); } else if (property.HasAttribute(typeof(AutoUISliderAttribute))) // Slider attributes { control = new SliderFieldControl(); } else if (pType.IsAssignableFrom(typeof(double)) || pType.IsAssignableFrom(typeof(int))) // Numbers { control = new SliderFieldControl(); } else if (pType == typeof(Angle)) // Angles { control = new SliderFieldControl(); } else if (pType == typeof(bool)) // Booleans { control = new CheckBoxFieldControl(); } else if (pType == typeof(NB.Bool6D)) // Bool6Ds { control = new Bool6DFieldControl(); } else if (pType == typeof(NG.Vector)) // Vectors { control = new VectorFieldControl(); } else if (pType.IsEnum) // Enums { control = new ComboFieldControl(); } //else if (pType == typeof(string) && !property.CanWrite) // Text block //{ // var tb = new TextBlock(); // tb.SetBinding(TextBlock.TextProperty, new Binding(property.Name)); // collection.Add(tb); //} else // Everything else! { control = new TextFieldControl(); } if (control != null) { control.AdaptTo(property); collection.Add(control); } } else if (member is MethodInfo) { Button button = new Button(); button.Command = new InvokeMethodCommand(source, (MethodInfo)member); AutoUIAttribute autoAtt = member.GetCustomAttribute <AutoUIAttribute>(); if (autoAtt != null) { // Use attribute-defined label if present: if (autoAtt != null && !string.IsNullOrWhiteSpace(autoAtt.Label)) { button.Content = autoAtt.Label; } // Otherwise, use property name: else { button.Content = member.Name; } // Label binding: if (!string.IsNullOrWhiteSpace(autoAtt?.LabelBinding)) { var bind = new Binding(autoAtt?.LabelBinding); //bind.FallbackValue = Label; button.SetBinding(Button.ContentProperty, bind); } // Visibility if (!string.IsNullOrWhiteSpace(autoAtt?.VisibilityBinding)) { var vB = new Binding(autoAtt.VisibilityBinding); vB.Converter = new Converters.VisibilityConverter(); button.SetBinding(Button.VisibilityProperty, vB); } // Tooltip if (!string.IsNullOrWhiteSpace(autoAtt?.ToolTip)) { button.ToolTip = autoAtt.ToolTip; } } collection.Add(button); } } }