Heim  >  Artikel  >  Backend-Entwicklung  >  Ein sehr leistungsfähiges Control-PropertyGrid

Ein sehr leistungsfähiges Control-PropertyGrid

零下一度
零下一度Original
2017-06-24 09:49:135873Durchsuche

PropertyGrid ist ein sehr leistungsfähiges Steuerelement. Ein Vorteil der Verwendung dieses Steuerelements als Eigenschaftseinstellungsfeld besteht darin, dass Sie sich nur auf den Code und nicht auf die Darstellung der Benutzeroberfläche konzentrieren müssen standardmäßig auf dem Variablentyp. Dies führt jedoch auch zu einem Problem: Die Verwendung des Steuerelements ist nicht besonders flexibel, hauptsächlich weil Sie das Steuerelement nicht entsprechend Ihren Anforderungen auswählen können. Wenn Sie beispielsweise das Slider-Steuerelement zum Festlegen einer int-Variablen verwenden müssen, Standardmäßig ist das PropertyGrid auf Die Vorlagenauswahl wird nicht unterstützt. Ich habe im Internet viele Informationen gefunden, die im Grunde die Implementierung von WinForm vorstellten, hauptsächlich unter Verwendung der IWindowFromService-Schnittstelle. Ich habe später keine geeignete Demo für WPF gefunden, nachdem ich auf die offizielle Demo von DEVExpress verwiesen hatte Basierend auf WPF und DEV 16.2 implementiert PropertyGrid Demo grundsätzlich die oben genannten Funktionen.

Um dies zu erreichen, müssen Sie eine DataTemplateSeletor-Klasse anpassen, die auch den Kerncode dieses Artikels darstellt.

1. Erstellen Sie ein benutzerdefiniertes CustomPropertyGrid-Steuerelement:

 1 <UserControl 2     x:Class="PropertyGridDemo.PropertyGridControl.CustomPropertyGrid" 3     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6     xmlns:dxprg="http://schemas.devexpress.com/winfx/2008/xaml/propertygrid" 7     xmlns:local="clr-namespace:PropertyGridDemo.PropertyGridControl" 8     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 9     d:DesignHeight="300"10     d:DesignWidth="300"11     mc:Ignorable="d">12     <UserControl.Resources>13         <ResourceDictionary>14             <ResourceDictionary.MergedDictionaries>15                 <!--  资源字典  -->16                 <ResourceDictionary Source="../PropertyGridControl/DynamicallyAssignDataEditorsResources.xaml" />17             </ResourceDictionary.MergedDictionaries>18         </ResourceDictionary>19     </UserControl.Resources>20     <Grid>21         <!--  PropertyDefinitionStyle:定义属性描述的风格模板  -->22         <!--  PropertyDefinitionTemplateSelector:定义一个模板选择器,对应一个继承自DataTemplateSelector的类  -->23         <!--  PropertyDefinitionsSource:定义一个获取数据属性集合的类,对应一个自定义类(本Demo中对应DataEditorsViewModel)  -->24         <dxprg:PropertyGridControl25             x:Name="PropertyGridControl"26             Margin="24"27             DataContextChanged="PropertyGridControl_DataContextChanged"28             ExpandCategoriesWhenSelectedObjectChanged="True"29             PropertyDefinitionStyle="{StaticResource DynamicallyAssignDataEditorsPropertyDefinitionStyle}"30             PropertyDefinitionTemplateSelector="{StaticResource DynamicallyAssignDataEditorsTemplateSelector}"31             PropertyDefinitionsSource="{Binding Path=Properties, Source={StaticResource DemoDataProvider}}"32             ShowCategories="True"33             ShowDescriptionIn="Panel" />34     </Grid>35 </UserControl>
CustomPropertyGrid

Das Das vom Steuerelement verwendete Ressourcenwörterbuch lautet wie folgt:

 1 <ResourceDictionary 2     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5     xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors" 6     xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid" 7     xmlns:dxprg="http://schemas.devexpress.com/winfx/2008/xaml/propertygrid" 8     xmlns:local="clr-namespace:PropertyGridDemo.PropertyGridControl" 9     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"10     mc:Ignorable="d">11 12     <local:DynamicallyAssignDataEditorsTemplateSelector x:Key="DynamicallyAssignDataEditorsTemplateSelector" />13     <local:DataEditorsViewModel x:Key="DemoDataProvider" />14 15     <DataTemplate x:Key="DescriptionTemplate">16         <RichTextBox17             x:Name="descriptionRichTextBox"18             MinWidth="150"19             HorizontalContentAlignment="Stretch"20             Background="Transparent"21             BorderThickness="0"22             Foreground="{Binding Path=(TextElement.Foreground), RelativeSource={RelativeSource TemplatedParent}}"23             IsReadOnly="True"24             IsTabStop="False" />25     </DataTemplate>26     <DataTemplate x:Key="descriptionTemplate">27         <RichTextBox28             x:Name="descriptionRichTextBox"29             MinWidth="150"30             HorizontalContentAlignment="Stretch"31             Background="Transparent"32             BorderThickness="0"33             Foreground="{Binding Path=(TextElement.Foreground), RelativeSource={RelativeSource TemplatedParent}}"34             IsReadOnly="True"35             IsTabStop="False" />36     </DataTemplate>37 38     <!--  设置控件的全局样式和数据绑定  -->39     <Style x:Key="DynamicallyAssignDataEditorsPropertyDefinitionStyle" TargetType="dxprg:PropertyDefinition">40         <Setter Property="Path" Value="{Binding Name}" />41         <!--<Setter Property="Header" Value="{Binding Converter={StaticResource PropertyDescriptorToDisplayNameConverter}}"/>-->42         <Setter Property="Description" Value="{Binding}" />43         <Setter Property="DescriptionTemplate" Value="{StaticResource descriptionTemplate}" />44     </Style>45     <Style x:Key="DescriptionContainerStyle" TargetType="dxprg:PropertyDescriptionPresenterControl">46         <Setter Property="ShowSelectedRowHeader" Value="False" />47         <Setter Property="MinHeight" Value="70" />48     </Style>49 50     <Style TargetType="Slider">51         <Setter Property="Margin" Value="2" />52     </Style>53     <Style TargetType="dxe:ComboBoxEdit">54         <Setter Property="IsTextEditable" Value="False" />55         <Setter Property="ApplyItemTemplateToSelectedItem" Value="True" />56         <Setter Property="Margin" Value="2" />57     </Style>58 59     <!--  测试直接从DataTemplate获取控件  -->60     <DataTemplate x:Key="SliderTemplate" DataType="local:SliderExtend">61         <!--<dxprg:PropertyDefinition>62             <dxprg:PropertyDefinition.CellTemplate>-->63         <!--<DataTemplate>-->64         <StackPanel x:Name="Root">65             <Slider66                 Maximum="{Binding Path=Max}"67                 Minimum="{Binding Path=Min}"68                 Value="{Binding Path=Value}" />69             <TextBlock Text="{Binding Path=Value}" />70         </StackPanel>71         <!--</DataTemplate>-->72         <!--</dxprg:PropertyDefinition.CellTemplate>73         </dxprg:PropertyDefinition>-->74     </DataTemplate>75 76     <DataTemplate x:Key="ComboBoxEditItemTemplate" DataType="Tuple">77         <TextBlock78             Height="20"79             Margin="5,3,0,0"80             VerticalAlignment="Center"81             Text="{Binding Item1}" />82     </DataTemplate>83 </ResourceDictionary>
ResourceDictionary

2. Schreiben Sie die entsprechende Vorlage Auswahlklasse DynamicallyAssignDataEditorsTemplateSelector :

  1 using DevExpress.Xpf.Editors;  2 using DevExpress.Xpf.PropertyGrid;  3 using System.ComponentModel;  4 using System.Reflection;  5 using System.Windows;  6 using System.Windows.Controls;  7 using System.Windows.Data;  8   9 namespace PropertyGridDemo.PropertyGridControl 10 { 11     public class DynamicallyAssignDataEditorsTemplateSelector : DataTemplateSelector 12     { 13         private PropertyDescriptor _property = null; 14         private RootPropertyDefinition _element = null; 15         private PropertyDataContext _propertyDataContext => App.PropertyGridDataContext; 16  17         /// <summary> 18         /// 当重写在派生类中,返回根据自定义逻辑的 <see cref="T:System.Windows.DataTemplate" /> 。 19         /// </summary> 20         /// <param name="item">数据对象可以选择模板。</param> 21         /// <param name="container">数据对象。</param> 22         /// <returns> 23         /// 返回 <see cref="T:System.Windows.DataTemplate" /> 或 null。默认值为 null。 24         /// </returns> 25         public override DataTemplate SelectTemplate(object item, DependencyObject container) 26         { 27             _element = (RootPropertyDefinition)container; 28             DataTemplate resource = TryCreateResource(item); 29             return resource ?? base.SelectTemplate(item, container); 30         } 31  32         /// <summary> 33         /// Tries the create resource. 34         /// </summary> 35         /// <param name="item">The item.</param> 36         /// <returns></returns> 37         private DataTemplate TryCreateResource(object item) 38         { 39             if (!(item is PropertyDescriptor)) return null; 40             PropertyDescriptor pd = (PropertyDescriptor)item; 41             _property = pd; 42             var customUIAttribute = (CustomUIAttribute)pd.Attributes[typeof(CustomUIAttribute)]; 43             if (customUIAttribute == null) return null; 44             var customUIType = customUIAttribute.CustomUI; 45             return CreatePropertyDefinitionTemplate(customUIAttribute); 46         } 47  48         /// <summary> 49         /// Gets the data context. 50         /// </summary> 51         /// <param name="dataContextPropertyName">Name of the data context property.</param> 52         /// <returns></returns> 53         private object GetDataContext(string dataContextPropertyName) 54         { 55             PropertyInfo property = _propertyDataContext?.GetType().GetProperty(dataContextPropertyName); 56             if (property == null) return null; 57             return property.GetValue(_propertyDataContext, null); 58         } 59  60         /// <summary> 61         /// Creates the slider data template. 62         /// </summary> 63         /// <param name="customUIAttribute">The custom UI attribute.</param> 64         /// <returns></returns> 65         private DataTemplate CreateSliderDataTemplate(CustomUIAttribute customUIAttribute) 66         { 67             DataTemplate ct = new DataTemplate(); 68             ct.VisualTree = new FrameworkElementFactory(typeof(StackPanel)); 69             ct.VisualTree.SetValue(StackPanel.DataContextProperty, GetDataContext(customUIAttribute.DataContextPropertyName)); 70  71             FrameworkElementFactory sliderFactory = new FrameworkElementFactory(typeof(Slider)); 72             sliderFactory.SetBinding(Slider.MaximumProperty, new Binding(nameof(SliderUIDataContext.Max))); 73             sliderFactory.SetBinding(Slider.MinimumProperty, new Binding(nameof(SliderUIDataContext.Min))); 74             sliderFactory.SetBinding(Slider.SmallChangeProperty, new Binding(nameof(SliderUIDataContext.SmallChange))); 75             sliderFactory.SetBinding(Slider.LargeChangeProperty, new Binding(nameof(SliderUIDataContext.LargeChange))); 76             sliderFactory.SetBinding(Slider.ValueProperty, new Binding(nameof(SliderUIDataContext.Value))); 77             ct.VisualTree.AppendChild(sliderFactory); 78  79             FrameworkElementFactory textFacotry = new FrameworkElementFactory(typeof(TextBlock), "TextBlock"); 80             textFacotry.SetValue(TextBlock.TextProperty, new Binding(nameof(SliderUIDataContext.Value))); 81             //textBoxFactory.AddHandler(TextBox.IsVisibleChanged, new DependencyPropertyChangedEventHandler(SearchBoxVisibleChanged)); 82             ct.VisualTree.AppendChild(textFacotry); 83             ct.Seal(); 84             return ct; 85         } 86  87         /// <summary> 88         /// Creates the ComboBox edit template. 89         /// </summary> 90         /// <param name="customUIAttribute">The custom UI attribute.</param> 91         /// <returns></returns> 92         private DataTemplate CreateComboBoxEditTemplate(CustomUIAttribute customUIAttribute) 93         { 94             DataTemplate template = new DataTemplate(); 95             template.VisualTree = new FrameworkElementFactory(typeof(DockPanel)); 96             template.VisualTree.SetValue(DockPanel.DataContextProperty, GetDataContext(customUIAttribute.DataContextPropertyName)); 97  98             FrameworkElementFactory textFactory = new FrameworkElementFactory(typeof(TextBlock)) ; 99             textFactory.SetValue(TextBlock.TextProperty, new Binding(nameof(ComboBoxEditDataContext.Name)));100             template.VisualTree.AppendChild(textFactory);101 102             FrameworkElementFactory comboBoxEditFactory = new FrameworkElementFactory(typeof(ComboBoxEdit));103             comboBoxEditFactory.SetBinding(ComboBoxEdit.ItemsSourceProperty, new Binding(nameof(ComboBoxEditDataContext.ItemSource)));104             comboBoxEditFactory.SetBinding(ComboBoxEdit.EditValueProperty, new Binding(nameof(ComboBoxEditDataContext.EditValue)));105             comboBoxEditFactory.SetBinding(ComboBoxEdit.SelectedIndexProperty, new Binding(nameof(ComboBoxEditDataContext.SelectedIndex)));106             comboBoxEditFactory.SetValue(ComboBoxEdit.ItemTemplateProperty, (DataTemplate)_element.TryFindResource("ComboBoxEditItemTemplate"));107             template.VisualTree.AppendChild(comboBoxEditFactory);108             template.Seal();109             return template;110         }111 112         /// <summary>113         /// Creates the property definition template.114         /// </summary>115         /// <param name="customUIAttribute">The custom UI attribute.</param>116         /// <returns></returns>117         private DataTemplate CreatePropertyDefinitionTemplate(CustomUIAttribute customUIAttribute)118         {119             DataTemplate dataTemplate = new DataTemplate();120             DataTemplate cellTemplate = null;//单元格模板121             FrameworkElementFactory factory = new FrameworkElementFactory(typeof(PropertyDefinition));122             dataTemplate.VisualTree = factory;123             switch (customUIAttribute.CustomUI)124             {125                 case CustomUITypes.Slider:126                     cellTemplate = CreateSliderDataTemplate(customUIAttribute); break;127                     //cellTemplate = (DataTemplate)_element.TryFindResource("SliderTemplate");break;128                 case CustomUITypes.ComboBoxEit:129                     cellTemplate = CreateComboBoxEditTemplate(customUIAttribute);break;130                 131             }132 133             if (cellTemplate != null)134             {135                 factory.SetValue(PropertyDefinition.CellTemplateProperty, cellTemplate);136                 dataTemplate.Seal();137 138             }139             else140             {141                 return null;142             }143             return dataTemplate;144         }145     }146 }
DynamicallyAssignDataEditorsTemplateSelector
using System.Collections.Generic;using System.ComponentModel;using System.Linq;namespace PropertyGridDemo.PropertyGridControl
{/// <summary>///初始化所有属性并调用模板选择器进行匹配/// </summary>public class DataEditorsViewModel
    {public IEnumerable<PropertyDescriptor> Properties { get { return TypeDescriptor.GetProperties(typeof(TestPropertyGrid)).Cast<PropertyDescriptor>(); } }
    }
}
DataEditorsViewModel

3. Schreiben Sie eine Eigenschaft CustomUIType, die zum Erstellen von Vorlagen verwendet werden kann:

using System;namespace PropertyGridDemo.PropertyGridControl
{public class CustomUIType
    {

    }public enum CustomUITypes
    {
        Slider,
        ComboBoxEit,
        SpinEdit,
        CheckBoxEdit
    }

    [AttributeUsage(AttributeTargets.Property)]internal class CustomUIAttribute : Attribute
    {public string DataContextPropertyName { get; set; }public CustomUITypes CustomUI { get; set; }/// <summary>/// 自定义控件属性构造函数/// </summary>/// <param name="uiTypes">The UI types.</param>/// <param name="dataContextPropertyName">Name of the data context property.</param>internal CustomUIAttribute(CustomUITypes uiTypes, string dataContextPropertyName)
        {
            CustomUI = uiTypes;
            DataContextPropertyName = dataContextPropertyName;
        }
    }

}
CustomUIType

4. Schreiben Sie die entsprechende DataContext-Klasse TestPropertyGrid:

  1 using DevExpress.Mvvm.DataAnnotations;  2 using System;  3 using System.ComponentModel;  4 using System.ComponentModel.DataAnnotations;  5 using System.Timers;  6 using System.Windows;  7   8 namespace PropertyGridDemo.PropertyGridControl  9 { 10     [MetadataType(typeof(DynamicallyAssignDataEditorsMetadata))] 11     public class TestPropertyGrid : PropertyDataContext 12     { 13         private double _count = 0; 14         private SliderUIDataContext _countSource = null; 15         private ComboBoxEditDataContext _comboSource = null; 16         private double _value=1; 17  18         public TestPropertyGrid() 19         { 20             Password = "1111111"; 21             Notes = "Hello"; 22             Text = "Hello hi"; 23         } 24  25         [Browsable(false)] 26         public SliderUIDataContext CountSource 27         { 28             get 29             { 30                 if (_countSource != null) 31                 { 32  33                     return _countSource; 34                 } 35                 else 36                 { 37                     _countSource = new SliderUIDataContext(0, 100, Count, 0.1, 1); 38                     _countSource.PropertyChanged += (object o, PropertyChangedEventArgs e) => 39                     { 40                         this.Count = _countSource.Value; 41                     }; 42                     return _countSource; 43                 } 44             } 45         } 46  47         [Browsable(false)] 48         public ComboBoxEditDataContext ComboSource 49         { 50             get 51             { 52                 if(_comboSource==null) 53                 { 54                     _comboSource =new ComboBoxEditDataContext(ComboBoxEditItemSource.TestItemSource,Value); 55                     _comboSource.PropertyChanged += (object o, PropertyChangedEventArgs e) => 56                       { 57                           this.Value =Convert.ToDouble(_comboSource.EditValue.Item2); 
 58                       }; 59                     60                 } 61                 return _comboSource; 62             } 63         } 64  65         [Display(Name = "SliderEdit", GroupName = "CustomUI")] 66         [CustomUI(CustomUITypes.Slider, nameof(CountSource))] 67         public double Count 68         { 69             get => _count; 70             set 71             { 72                 _count = value; 73                 CountSource.Value = value; 
 74                 RaisePropertyChanged(nameof(Count)); 75             } 76         } 77  78         [Display(Name = "ComboBoxEditItem", GroupName = "CustomUI")] 79         [CustomUI(CustomUITypes.ComboBoxEit, nameof(ComboSource))] 80         public double Value 81         { 82             get => _value; 83             set 84             { 85                 if (_value == value) return; 86                 _value = value; 87                 //ComboSource.Value = value; 88                 RaisePropertyChanged(nameof(Value)); 89             } 90         } 91  92         [Display(Name = "Password", GroupName = "DefaultUI")] 93         public string Password { get; set; } 94  95         [Display(Name = "TextEdit", GroupName = "DefaultUI")] 96         public string Text { get; set; } 97  98         [Display(Name = "Notes", GroupName = "DefaultUI")] 99         public string Notes { get; set; }100 101 102         [Display(Name = "Double", GroupName = "DefaultUI")]103         [DefaultValue(1)]104         public double TestDouble { get; set; }105 106         [Display(Name = "Items", GroupName = "DefaultUI")]107         [DefaultValue(Visibility.Visible)]108         public Visibility TestItems { get; set; }109     }110 111     public static class DynamicallyAssignDataEditorsMetadata112     {113         public static void BuildMetadata(MetadataBuilder<TestPropertyGrid> builder)114         {115             builder.Property(x => x.Password)116                 .PasswordDataType();117 118             builder.Property(x => x.Notes)119                 .MultilineTextDataType();120         }121     }122 }
TestPropertyGrid

Weitere in dieser Klasse verwendete Klassen umfassen hauptsächlich die folgenden Klassen:

namespace PropertyGridDemo.PropertyGridControl
{public class SliderUIDataContext:PropertyDataContext
    {private double _value = 0;private double _max = 0;private double _min = 0;private double _smallChange = 1;private double _largeChange=1;public SliderUIDataContext()
        {

        }/// <summary>/// Initializes a new instance of the <see cref="SliderUIDataContext"/> class./// </summary>/// <param name="min">The minimum.</param>/// <param name="max">The maximum.</param>/// <param name="value">The value.</param>/// <param name="smallChange">The small change.</param>/// <param name="largeChange">The large change.</param>public SliderUIDataContext(double min, double max, double value,double smallChange=0.01,double largeChange=0.1)
        {
            SmallChange = smallChange;
            LargeChange = largeChange;
            Max = max;
            Min = min;
            Value = value;
        }/// <summary>/// Gets or sets the small change./// </summary>/// <value>/// The small change./// </value>public double SmallChange
        {get => _smallChange;set{if (value == _min) return;
                _min = value;
                RaisePropertyChanged(nameof(SmallChange));
            }
        }/// <summary>/// Gets or sets the large change./// </summary>/// <value>/// The large change./// </value>public double LargeChange
        {get => _largeChange;set{if (Value == _largeChange) return;
                _largeChange = value;
                RaisePropertyChanged(nameof(LargeChange));
            }
        }/// <summary>/// Gets or sets the maximum./// </summary>/// <value>/// The maximum./// </value>public double Max
        {get => _max;set{if (value == _max) return;
                _max = value;
                RaisePropertyChanged(nameof(Max));
            }
        }/// <summary>/// Gets or sets the minimum./// </summary>/// <value>/// The minimum./// </value>public double Min
        {get => _min;set{if (value == _min) return;
                _min = value;
                RaisePropertyChanged(nameof(Min));
            }
        }/// <summary>/// Gets or sets the value./// </summary>/// <value>/// The value./// </value>public double Value
        {get => _value;set{if (value == _value) return;
                _value = value;
                RaisePropertyChanged(nameof(Value));
            }
        }
    }
}
SliderUIDataContext
using System;using System.Linq;namespace PropertyGridDemo.PropertyGridControl
{public class ComboBoxEditDataContext:PropertyDataContext
    {private Tuple<string, object>[] _itemSource;private Tuple<string, object> _editValue;private int _selectedIndex;/// <summary>/// Initializes a new instance of the <see cref="ComboBoxEditDataContext"/> class./// </summary>/// <param name="itemSource">The item source.</param>/// <param name="editValue">The edit value.</param>public ComboBoxEditDataContext(Tuple<string,object>[] itemSource,Tuple<string,object> editValue)
        {
            _itemSource = itemSource;
            _editValue = _itemSource.FirstOrDefault(x => x?.Item1.ToString() == editValue?.Item1.ToString() && x?.Item2?.ToString() == x?.Item2?.ToString());
        }/// <summary>/// Initializes a new instance of the <see cref="ComboBoxEditDataContext" /> class./// </summary>/// <param name="itemSource">The item source.</param>/// <param name="value">The value.</param>public ComboBoxEditDataContext(Tuple<string, object>[] itemSource, object value)
        {
            _itemSource = itemSource;
            _editValue = _itemSource.FirstOrDefault(x => x?.Item2.ToString() == value.ToString() );
        }public string Name
        {get;set;
        }/// <summary>/// Gets or sets the item source./// </summary>/// <value>/// The item source./// </value>public Tuple<string,object>[] ItemSource
        {get => _itemSource;set{//if (_itemSource == value) return;_itemSource = value;
                RaisePropertyChanged(nameof(ItemSource));
            }
        }/// <summary>/// Gets or sets the edit value./// </summary>/// <value>/// The edit value./// </value>public Tuple<string,object> EditValue
        {get => _editValue;set{if (_editValue == value) return;
                _editValue = value;
                RaisePropertyChanged(nameof(EditValue));
            }
        }public object Value
        {set{
                EditValue = ItemSource.FirstOrDefault(x => x.Item2.Equals(value));
            }
        }/// <summary>/// Gets or sets the index of the selected./// </summary>/// <value>/// The index of the selected./// </value>public int SelectedIndex
        {get => _selectedIndex;set{if (_selectedIndex == value || value==-1) return;
                _selectedIndex = value;
                EditValue = ItemSource[value];
                RaisePropertyChanged(nameof(SelectedIndex));
            }
        }
    }
}
ComboBoxEditDataContext
using System.ComponentModel;namespace PropertyGridDemo.PropertyGridControl
{public class PropertyDataContext:INotifyPropertyChanged
    {/// <summary>/// 在更改属性值时发生。/// </summary>public event PropertyChangedEventHandler PropertyChanged;/// <summary>/// 触发属性变化/// </summary>/// <param name="propertyName"></param>public virtual void RaisePropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
PropertyDataContext
using System;namespace PropertyGridDemo.PropertyGridControl
{internal static class ComboBoxEditItemSource
    {internal static Tuple<string, object>[] TestItemSource = new Tuple<string, object>[] {new Tuple<string, object>("1",1),new Tuple<string, object>("2",2),new Tuple<string, object>("3",3)
        };
    }
}
ComboBoxEditItemSource

5.将以上的CustomPropertyGrid丢进容器中即可,这里我直接用Mainwindow来演示:

 1 <Window 2     x:Class="PropertyGridDemo.MainWindow" 3     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5     xmlns:PropertyGridControl="clr-namespace:PropertyGridDemo.PropertyGridControl" 6     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 7     xmlns:local="clr-namespace:PropertyGridDemo" 8     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 9     Title="MainWindow"10     Width="525"11     Height="350"12     WindowState="Maximized"13     mc:Ignorable="d">14     <Grid Margin="10">15         <Grid.ColumnDefinitions>16             <ColumnDefinition Width="259*" />17             <ColumnDefinition Width="259*" />18         </Grid.ColumnDefinitions>19 20         <TextBox21             x:Name="OutputBox"22             Grid.ColumnSpan="1"23             HorizontalScrollBarVisibility="Auto"24             ScrollViewer.CanContentScroll="True" />25         <PropertyGridControl:CustomPropertyGrid x:Name="PropertyGrid" Grid.Column="1" />26     </Grid>27 </Window>
MainWindow

 

运行示意图:

以上就是自定义PropertyGrid控件的实现代码,本人只实现了简单的Slider和ComboBoxEdit控件,实际上可以根据自己的需要仿照以上的方法扩展到其他控件,这个就看需求了。

个人感觉以上方案还是有所欠缺,主要是自定义控件的模板是由代码生成的,如果可以直接从资源文件中读取将会更加方便,不过本人尝试了几次并不能成功的实现数据的绑定,如果大家有什么好的解决方案欢迎在评论区留言,也欢迎大家在评论区进行讨论。

以上内容均为原创,转发请注明出处,谢谢!

 

Das obige ist der detaillierte Inhalt vonEin sehr leistungsfähiges Control-PropertyGrid. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn