您好,登錄后才能下訂單哦!
什么是PropertyGrid控件?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
PropertyGrid是一個很強大的控件,使用該控件做屬性設置面板的一個好處就是你只需要專注于代碼而無需關注UI的呈現,PropertyGrid會默認根據變量類型選擇合適的控件顯示。但是這也帶來了一個問題,就是控件的使用變得不是特別靈活,主要表現在你無法根據你的需求很好的選擇控件,比如當你需要用Slider控件來設置int型變量時,PropertyGrid默認的模板選擇器是不支持的。網上找了許多資料基本都是介紹WinForm的實現方式,主要用到了IWindowFromService這個接口,并未找到合適的適合WPF的Demo,后來在參考了DEVExpress的官方Demo之后我做了一個基于WPF和DEV 16.2的PropertyGrid Demo,基本實現了上述功能。
為了實現這一點,需要自定義一個DataTemplateSeletor類,這也是本文的核心代碼。
1.創建一個CustomPropertyGrid自定義控件:
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>
該控件使用的資源字典如下:
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>
2.編寫對應的模板選擇類 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 }
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>(); } } } }
3.編寫一個可用于構建模板的屬性 CustomUIType:
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; } } }
4.編寫對應的DataContext類 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 }
該類中用到的其他類主要有以下幾個,以下幾個類主要用于數據綁定:
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)); } } } }
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)); } } } }
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)); } } }
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) }; } }
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>
運行示意圖:
以上就是自定義PropertyGrid控件的實現代碼,本人只實現了簡單的Slider和ComboBoxEdit控件,實際上可以根據自己的需要仿照以上的方法擴展到其他控件,這個就看需求了。
個人感覺以上方案還是有所欠缺,主要是自定義控件的模板是由代碼生成的,如果可以直接從資源文件中讀取將會更加方便,不過本人嘗試了幾次并不能成功的實現數據的綁定,如果大家有什么好的解決方案歡迎在評論區留言,也歡迎大家在評論區進行討論。
以上內容均為原創,轉發請注明出處,謝謝!
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。