using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.ComponentModel; using System.Reflection; namespace AIStudio.Wpf.DiagramDesigner.Controls { /// <summary> /// Interaction logic for PropertiesView.xaml /// </summary> public partial class PropertiesView : UserControl { #region SelectedObject public static readonly DependencyProperty SelectedObjectProperty = DependencyProperty.Register(nameof(SelectedObject), typeof(object), typeof(PropertiesView), new UIPropertyMetadata(null, OnSelectedObjectChanged)); public object SelectedObject { get { return (object)GetValue(SelectedObjectProperty); } set { SetValue(SelectedObjectProperty, value); } } private static void OnSelectedObjectChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { PropertiesView propertyInspector = o as PropertiesView; if (propertyInspector != null) propertyInspector.OnSelectedObjectChanged((object)e.OldValue, (object)e.NewValue); } protected virtual void OnSelectedObjectChanged(object oldValue, object newValue) { DisplayProperties(); } #endregion //SelectedObject public static readonly DependencyProperty NeedBrowsableProperty = DependencyProperty.Register(nameof(NeedBrowsable), typeof(bool), typeof(PropertiesView), new UIPropertyMetadata(true)); public bool NeedBrowsable { get { return (bool)GetValue(NeedBrowsableProperty); } set { SetValue(NeedBrowsableProperty, value); } } public bool CustomSetting { get; set; } public PropertiesView() { InitializeComponent(); this.Loaded += PropertiesView_Loaded; } private void PropertiesView_Loaded(object sender, RoutedEventArgs e) { DisplayProperties(); } private void DisplayProperties() { _panel.Children.Clear(); ClearGrid(); if (SelectedObject != null) { if (CustomSetting == true) { if (SelectedObject.GetType().GetProperty("PropertiesSetting") != null) { Dictionary<string, string> settings = SelectedObject.GetType().GetProperty("PropertiesSetting").GetValue(SelectedObject) as Dictionary<string, string>; int row = 0; foreach (var setting in settings) { var prop = SelectedObject.GetType().GetProperty(setting.Key); DisplayProperty(prop, row, setting.Value); row++; } } } else { int row = 0; foreach (var prop in SelectedObject.GetType().GetProperties()) { var attr = prop.GetCustomAttributes(typeof(BrowsableAttribute), true); if (NeedBrowsable == false && (attr.Length == 0 || (attr[0] as BrowsableAttribute).Browsable)) { DisplayProperty(prop, row); row++; } else if (NeedBrowsable == true && (attr.Length > 0 && (attr[0] as BrowsableAttribute).Browsable)) { DisplayProperty(prop, row); row++; } } } _panel.Children.Add(_gridContainer); } else { _panel.Children.Add(_label); } } private void ClearGrid() { _grid.RowDefinitions.Clear(); for (int i = _grid.Children.Count - 1; i >= 0; i--) { if (_grid.Children[i] != _vLine && _grid.Children[i] != _splitter) _grid.Children.RemoveAt(i); } } private void DisplayProperty(PropertyInfo prop, int row, string name = null) { var rowDef = new RowDefinition(); rowDef.Height = new GridLength(Math.Max(20, this.FontSize * 2)); _grid.RowDefinitions.Add(rowDef); var tb = new TextBlock() { Text = prop.Name }; if (name != null) { tb.Text = name; tb.ToolTip = prop.Name; } else { var displayAttr = prop.GetCustomAttributes(typeof(DisplayNameAttribute), true); if (displayAttr.Length > 0) { tb.Text = (displayAttr[0] as DisplayNameAttribute).DisplayName; tb.ToolTip = prop.Name; } } tb.Margin = new Thickness(4); Grid.SetColumn(tb, 0); Grid.SetRow(tb, _grid.RowDefinitions.Count - 1); _grid.Children.Add(tb); var line = new Line(); line.Style = (Style)border.Resources["gridHorizontalLineStyle"]; Grid.SetRow(line, row); _grid.Children.Add(line); Style style = null; var styleNameAttr = prop.GetCustomAttributes(typeof(StyleNameAttribute), true); if (styleNameAttr.Length > 0) { style = this.FindResource((styleNameAttr[0] as StyleNameAttribute).Name) as Style; if (style != null) { ContentControl content = new ContentControl(); content.Style = style; content.DataContext = SelectedObject; Grid.SetColumn(content, 1); Grid.SetRow(content, _grid.RowDefinitions.Count - 1); _grid.Children.Add(content); } } if (style == null) { var ed = new TextBox(); ed.PreviewKeyDown += new KeyEventHandler(ed_KeyDown); ed.Margin = new Thickness(0); ed.VerticalAlignment = VerticalAlignment.Center; ed.BorderThickness = new Thickness(0); Grid.SetColumn(ed, 1); Grid.SetRow(ed, _grid.RowDefinitions.Count - 1); var binding = new Binding(prop.Name); binding.Source = SelectedObject; binding.ValidatesOnExceptions = true; binding.Mode = BindingMode.OneWay; if (prop.CanWrite) { var mi = prop.GetSetMethod(); if (mi != null && mi.IsPublic) binding.Mode = BindingMode.TwoWay; } ed.SetBinding(TextBox.TextProperty, binding); var template = (ControlTemplate)border.Resources["validationErrorTemplate"]; Validation.SetErrorTemplate(ed, template); _grid.Children.Add(ed); } } void ed_KeyDown(object sender, KeyEventArgs e) { var ed = sender as TextBox; if (ed != null) { if (e.Key == Key.Enter) { ed.GetBindingExpression(TextBox.TextProperty).UpdateSource(); e.Handled = true; } else if (e.Key == Key.Escape) ed.GetBindingExpression(TextBox.TextProperty).UpdateTarget(); } } } [AttributeUsage(AttributeTargets.Property)] public class StyleNameAttribute : Attribute { private string _name; public StyleNameAttribute(string name) { _name = name; } public string Name { get { return _name; } } } }