using OpenTap; using OpenTap.Addin.Annotation; using OpenTapEditor.UI; using System.ComponentModel; using System.Reflection; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Xml.Serialization; namespace OpenTapEditor.Provider { public class GridControlProvider { private static ITypeData resourceTypeData = TypeData.FromType(typeof(IResource)); /// /// 获取需要渲染的属性 /// /// /// public static Dictionary GetRenderProperty(object obj) { var res = new Dictionary(); var properties = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public); foreach (var property in properties) { if (property.GetCustomAttribute() != null) { res[property.Name] = property; } } return res; } /// /// 获取需要渲染的方法 /// /// /// public static Dictionary GetRenderMethods(object obj) { var res = new Dictionary(); var methods = obj.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (var method in methods) { if (method.GetCustomAttribute() != null) { res[method.Name] = method; } } return res; } private static FrameworkElement RanderElement(object source, PropertyInfo property) { if (property.GetCustomAttribute() is FilePathAttribute fpa) { FileSelector fs = new FileSelector() { Mode = fpa.Mode, Ext = fpa.FileExtension }; if (property.PropertyType == typeof(MacroString)) { BindingOperations.SetBinding(fs, FileSelector.FilePathProperty, new Binding(property.Name) { Source = source, Converter = MacroStringConverter.Instance, ConverterParameter = source, Mode = BindingMode.TwoWay, NotifyOnSourceUpdated = true }); } else { BindingOperations.SetBinding(fs, FileSelector.FilePathProperty, new Binding(property.Name) { Source = source, Mode = BindingMode.TwoWay, NotifyOnSourceUpdated = true }); } return fs; } if (property.GetCustomAttribute() is DynamicSelectAttribute dsa) { ComboBox combox = new ComboBox(); if (!string.IsNullOrEmpty(dsa.SourceName)) { BindingOperations.SetBinding(combox, ComboBox.ItemsSourceProperty, new Binding(dsa.SourceName) { Source = source, Mode = BindingMode.OneWay }); } if (!string.IsNullOrEmpty(dsa.DisplayName)) { combox.DisplayMemberPath = dsa.DisplayName; combox.SelectedValuePath = dsa.BindingName; BindingOperations.SetBinding(combox, ComboBox.SelectedValueProperty, new Binding(property.Name) { Source = source, Mode = BindingMode.TwoWay }); } else { BindingOperations.SetBinding(combox, ComboBox.TextProperty, new Binding(property.Name) { Source = source, Mode = BindingMode.TwoWay }); } return combox; } if (property.GetCustomAttribute() is BindingListAttribute bla) { var dataGrid = new DataGrid() { MinHeight = 100, HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled }; BindingOperations.SetBinding(dataGrid, DataGrid.ItemsSourceProperty, new Binding(bla.BindingName) { Source = source, Mode = BindingMode.TwoWay, }); dataGrid.CanUserAddRows = bla.CanAdd; dataGrid.AutoGenerateColumns = false; dataGrid.CanUserSortColumns = false; Type propertyType = source?.GetType()?.GetProperty(bla.BindingName)?.PropertyType; if (propertyType?.IsGenericType == true) { DataGridHelper.SetDataGridColumns(dataGrid, propertyType.GetGenericArguments()[0]); } else { DataGridHelper.SetDataGridColumns(dataGrid, propertyType); } return dataGrid; } if (property.PropertyType == typeof(bool?) || property.PropertyType == typeof(bool)) { CheckBox cb = new CheckBox(); cb.VerticalAlignment = VerticalAlignment.Center; BindingOperations.SetBinding(cb, CheckBox.IsCheckedProperty, new Binding(property.Name) { Source = source, Mode = BindingMode.TwoWay, }); return cb; } // 枚举 if (property.PropertyType.IsEnum) { ComboBox combox = new ComboBox(); combox.VerticalAlignment = VerticalAlignment.Center; combox.ItemsSource = System.Enum.GetNames(property.PropertyType); BindingOperations.SetBinding(combox, ComboBox.SelectedItemProperty, new Binding(property.Name) { Source = source, Mode = BindingMode.TwoWay }); return combox; } /// 参数 if (property.GetCustomAttribute() is TreeDataAttribute tda) { VariableTree tree = new VariableTree() { MinHeight = 100 }; BindingOperations.SetBinding(tree, VariableTree.DatasourceProperty, new Binding(property.Name) { Source = source, Mode = BindingMode.TwoWay }); return tree; } TextBox tb = new TextBox { IsReadOnly = !(property.CanWrite && property.SetMethod?.IsPublic == true) }; BindingOperations.SetBinding(tb, TextBox.TextProperty, new Binding(property.Name) { Source = source, Mode = tb.IsReadOnly ? BindingMode.OneWay : BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged }); return tb; } public static bool FilterMember(IMemberData member) { if (member.DeclaringType.DescendsTo(resourceTypeData) && member.Name == nameof(Resource.Name)) return true; if (member.GetAttribute() is BrowsableAttribute attr) return attr.Browsable; if (member.HasAttribute()) return true; return member.Attributes.Any(a => a is XmlIgnoreAttribute) == false && member.Writable; } public static Grid GetControl(object obj) { var grid = new Grid() { }; grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) }); grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) }); var properties = GetRenderProperty(obj); int i = 0; foreach (var key in properties.Keys) { var property = properties[key]; var display = property.GetCustomAttribute(); var label = new Label { Content = display.Name }; grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) }); grid.Children.Add(label); Grid.SetRow(label, i); Grid.SetColumn(label, 0); var element = RanderElement(obj, property); if (element != null) { grid.Children.Add(element); Grid.SetRow(element, i); Grid.SetColumn(element, 1); } i++; } foreach (var node in GetRenderMethods(obj)) { var method = node.Value; var display = method.GetCustomAttribute(); var btn = new Button { Content = display.Name }; btn.Click += (sender, e) => { method.Invoke(obj, null); }; grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) }); grid.Children.Add(btn); Grid.SetRow(btn, i); Grid.SetColumn(btn, 0); Grid.SetColumnSpan(btn, 2); i++; } if (obj is ITestStepParent tsp) { grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) }); var label = new Label { Content = "Break Condition" }; grid.Children.Add(label); Grid.SetRow(label, i); Grid.SetColumn(label, 0); var s = BreakConditionProperty.GetBreakCondition(tsp); var element = new BreakConditionCtrl { Source = tsp }; if (element != null) { grid.Children.Add(element); Grid.SetRow(element, i); Grid.SetColumn(element, 1); } } return grid; } } }