首页 > 其他分享 >WPF一个简单的属性编辑控件

WPF一个简单的属性编辑控件

时间:2024-05-25 18:12:50浏览次数:24  
标签:控件 set get child PropertyInfo new WPF public 属性

代码:

    public class PropertiesControl : Grid
    {

        [TypeConverter(typeof(LengthConverter))]
        public double RowHeight
        {
            get { return (double)GetValue(RowHeightProperty); }
            set { SetValue(RowHeightProperty, value); }
        }

        public static readonly DependencyProperty RowHeightProperty =
            DependencyProperty.Register("RowHeight", typeof(double), typeof(PropertiesControl), new PropertyMetadata(0d));

        public object Source
        {
            get { return (object)GetValue(SourceProperty); }
            set { SetValue(SourceProperty, value); }
        }

        public static readonly DependencyProperty SourceProperty =
            DependencyProperty.Register("Source", typeof(object), typeof(PropertiesControl), new PropertyMetadata(SourceChangedCallBack));

        private static void SourceChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PropertiesControl control = (PropertiesControl)d;
            if (e.OldValue == e.NewValue) return;
            control.Load();
        }

        GridSplitter splitter = new GridSplitter { Width = 2, HorizontalAlignment = HorizontalAlignment.Right };

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            splitter.SetBinding(BackgroundProperty, new Binding { Source = this, Path = new PropertyPath(BackgroundProperty) });
        }

        void Load()
        {
            Children.Clear();
            RowDefinitions.Clear();
            ColumnDefinitions.Clear();
            ColumnDefinitions.Add(new ColumnDefinition());
            ColumnDefinitions.Add(new ColumnDefinition());
            if (Source == null) return;
            PropertyDocument doc = PropertyDocument.Load(Source);
            if (doc.Children != null)
                Load(doc.Children);
            SetRowSpan(splitter, RowDefinitions.Count);
            Children.Add(splitter);
        }

        void Load(List<Property> properties)
        {
            if (properties == null) return;
            foreach (var child in properties)
            {
                RowDefinitions.Add(new RowDefinition());
                if (child.Children != null && child.Children.Count > 0)
                {
                    TextBlock group = new TextBlock { Text = child.PropertyInfo.Name, };
                    SetColumn(group, 0);
                    SetRow(group, RowDefinitions.Count - 1);
                    Children.Add(group);
                    Load(child.Children);
                    continue;
                }
                TextBlock text = new TextBlock { Text = child.PropertyInfo.Name, VerticalAlignment = VerticalAlignment.Center };
                SetColumn(text, 0);
                SetRow(text, RowDefinitions.Count - 1);
                LoadValueControl(child);
                Children.Add(text);
            }
        }

        void LoadValueControl(Property child)
        {
            FrameworkElement element;
            Binding binding = new Binding(child.Path) { Source = Source, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged };
            if (child.PropertyInfo.PropertyType.IsEnum)
            {
                Array enmus = Enum.GetValues(child.PropertyInfo.PropertyType);
                ComboBox comboBox = new ComboBox { ItemsSource = enmus, VerticalContentAlignment = VerticalAlignment.Center, BorderThickness = new Thickness(0), IsEnabled = !child.CanSet() };
                comboBox.SetBinding(Selector.SelectedItemProperty, binding);
                element = comboBox;
            }
            else if (child.PropertyInfo.PropertyType == typeof(bool))
            {
                CheckBox cb = new CheckBox { VerticalAlignment = VerticalAlignment.Center, IsEnabled = !child.CanSet() };
                cb.SetBinding(CheckBox.IsCheckedProperty, binding);
                element = cb;
            }
            else if (!child.CanSet())
            {
                TextBlock control = new TextBlock { VerticalAlignment = VerticalAlignment.Center };
                control.SetBinding(TextBlock.TextProperty, binding);
                element = control;
            }
            else
            {
                TextBox textBox = new TextBox { VerticalContentAlignment = VerticalAlignment.Center, BorderThickness = new Thickness(0) };
                textBox.SetBinding(TextBox.TextProperty, binding);
                element = textBox;
            }
            SetColumn(element, 1);
            SetRow(element, RowDefinitions.Count - 1);
            if (RowHeight > 0d)
                element.Height = RowHeight;
            element.Margin = new Thickness(0, 2, 0, 0);
            Children.Add(element);
        }
    }

    public class PropertyDocument
    {
        public object Value { get; set; }
        public List<Property>? Children { get; private set; }

        private PropertyDocument(object instance)
        {
            Value = instance;
        }

        public static PropertyDocument? Load(object instance)
        {
            if (instance == null) return null;
            var doc = new PropertyDocument(instance);
            if (instance != null)
                doc.Children = Property.LoadProperties(instance, null, doc);
            return doc;
        }
    }

    public class Property
    {
        public PropertyInfo PropertyInfo { get; set; }
        public Property? Parent { get; set; }
        public List<Property>? Children { get; private set; }
        public PropertyDocument Document { get; set; }
        public string Path
        {
            get
            {
                if (Parent != null)
                    return $"{Parent.Path}.{PropertyInfo.Name}";
                else
                    return $"{PropertyInfo.Name}";
            }
        }

        public Property(PropertyInfo propertyInfo, Property? parent, PropertyDocument doc)
        {
            PropertyInfo = propertyInfo;
            Parent = parent;
            Document = doc;
            Children = LoadProperties(GetValue(), this, Document);
        }

        public object? GetValue()
        {
            return PropertyInfo.GetValue(Parent == null ? Document.Value : Parent.GetValue());
        }

        public bool CanSet()
        {
            return CanSet(PropertyInfo);
        }

        public static bool CanSet(PropertyInfo propertyInfo)
        {
            return propertyInfo.CanWrite && propertyInfo.SetMethod != null && (propertyInfo.SetMethod.Attributes & MethodAttributes.Public) > 0;
        }

        public static bool CanGet(PropertyInfo propertyInfo)
        {
            return propertyInfo.CanRead && propertyInfo.GetMethod != null && (propertyInfo.GetMethod.Attributes & MethodAttributes.Public) > 0;
        }

        public static List<Property>? LoadProperties(object? instance, Property? parent, PropertyDocument doc)
        {
            if(instance == null) return null;
            Type type = instance.GetType();
            object? value;
            List<Property> properties = new List<Property>();
            var ps = type.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
            if (ps.Length <= 0 || type.IsValueType) return null;
            foreach (var p in ps)
            {
                if (!CanGet(p)) continue;
                value = p.GetValue(instance);
                Property property = new Property(p, parent, doc);
                properties.Add(property);
            }
            return properties;
        }
    }
View Code

使用方式:

<controls:PropertiesControl DockPanel.Dock="Right" Grid.Column="1" Source="{Binding Box}" RowHeight="30" Background="#FFEEEEEE" VerticalAlignment="Top"/>
    public class Box
    {
        public double X { get; set; }
        public double Y { get; set; }
        public double Width { get; set; }
        public double Height { get; set; }
        public Point Origin { get; set; }
        public bool Enabled { get; set; }
        public int Id { get; private set; }
    }
    public class TestVM : NotifyProperty, ITemplateView
    {
        public Box Box { get; set; }

        public TestVM()
        {
            Box = new Box { X = 100, Y = 100, Width = 100, Height = 100 };
        }
    }

直接绑定对象即可。

标签:控件,set,get,child,PropertyInfo,new,WPF,public,属性
From: https://www.cnblogs.com/RedSky/p/18212736

相关文章

  • WPF 加载本地HTML
    index.html代码高亮:<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>jQuery语法高亮示例</title><linkrel="stylesheet"href="https://cdnjs.cloudflare.com/a......
  • ThinkEditor跨平台BS电子病历编辑器控件具备哪些能力
            笔者从事医疗信息化行业工作10多年,对当前热门的BS架构的电子病历编辑器有一些自己的思考发出来供大家讨论,笔者信译,演示网址:www.thinkeditor.com。1.病历结构是否需要结构化        首先是陈旧的自定义字符串格式,虽格式灵活,但需自己编写病历格式解析......
  • 推荐2款开源、美观的WinForm UI控件库
    前言今天大姚给大家分享2款开源、美观的WinFormUI控件库,希望可以帮助到有需要的同学。WinForm介绍WinForm是一个传统的桌面应用程序框架,它基于Windows操作系统的原生控件和窗体。通过简单易用的API,开发者可以快速构建基于窗体的应用程序,并且可以利用多种控件和事件来实现应......
  • Idea中如何查看类的属性和实现
     ......
  • 使用python uiautomation模块,结合多线程快速寻找控件
    文章目录1.形式一2.形式二1.形式一该方法使用多线程进行搜索,主线程不会等待所有子线程返回结果后再继续执行,而是在获取队列中第一个结果后立即继续执行。优势在于一旦有子线程找到结果,主线程就能立即继续执行;劣势在于未找到结果的子线程会持续搜索,直到达到设定的最大......
  • 【WPF】WPF中调用winform的控件,winform始终置顶处理
    在WPF中调用windowFormsHost的控件时,由于渲染机制的问题总会出现各种问题,比如Winform的控件始终会出现在最顶层。在WPF项目中添加Microsoft.DwayneNeed.dll可以避免置顶问题<xmlns:interop=clr-namespace:Microsoft.DwayneNeed.Interop;assembly=Microsoft.DwayneNeed></xmln......
  • WPF Image ZoomIn ZoomOut
    //xaml<Windowx:Class="WpfApp109.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mi......
  • Mybatis框架 <insert> 标签内 useGeneratedKeys="true" 和 keyProperty="xxx" 属性
    useGeneratedKeys="true" 和 keyProperty="secondIndex" 这两个属性经常与MyBatis(Java持久层框架)的 <insert> 标签一起使用。这两个属性主要用于在插入记录后,从数据库返回的自动生成的主键或其他键值中,获取该键值并将其设置到Java对象的某个属性中。useGeneratedK......
  • .net 直接在DataGridView控件中修改单元格数据,并保存到数据库
    1.获取datagridview单元格修改的内容//单元格的值发生改变时触发事件privatevoiddataGridView1_CellValueChanged(objectsender,DataGridViewCellEventArgse){//获取当前行绑定的内容AppraisalBasesitem=(AppraisalBases)dataGridView1.Rows[e.RowIndex].Da......
  • 推荐一个WPF仪表盘开源控件
    前段时间,做服务器端监控系统,为了界面好看,采用WPF。硬件相关监控,比如CPU、内存等,想用仪表盘控件。网上找了很多这种控件,基本上都是第三方商业控件(虽然很漂亮,不过得money...)。最后在CodeProject上找到了一款还不错的开源的仪表盘控件CircularGauge。用了下该控件,感觉还不错......