2.编写对应的模板选择类 DynamicallyAssignDataEditorsTemplateSelector:
using DevExpress.Xpf.Editors;
using DevExpress.Xpf.PropertyGrid;
using System.ComponentModel;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace PropertyGridDemo.PropertyGridControl
{
public class DynamicallyAssignDataEditorsTemplateSelector : DataTemplateSelector
{
private PropertyDescriptor _property = null;
private RootPropertyDefinition _element = null;
private PropertyDataContext _propertyDataContext => App.PropertyGridDataContext;
/// <summary>
/// 当重写在派生类中,返回根据自定义逻辑的 <see cref="T:System.Windows.DataTemplate" /> 。
/// </summary>
/// <param name="item">数据对象可以选择模板。</param>
/// <param name="container">数据对象。</param>
/// <returns>
/// 返回 <see cref="T:System.Windows.DataTemplate" /> 或 null。默认值为 null。
/// </returns>
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
_element = (RootPropertyDefinition)container;
DataTemplate resource = TryCreateResource(item);
return resource ?? base.SelectTemplate(item, container);
}
/// <summary>
/// Tries the create resource.
/// </summary>
/// <param name="item">The item.</param>
/// <returns></returns>
private DataTemplate TryCreateResource(object item)
{
if (!(item is PropertyDescriptor)) return null;
PropertyDescriptor pd = (PropertyDescriptor)item;
_property = pd;
var customUIAttribute = (CustomUIAttribute)pd.Attributes[typeof(CustomUIAttribute)];
if (customUIAttribute == null) return null;
var customUIType = customUIAttribute.CustomUI;
return CreatePropertyDefinitionTemplate(customUIAttribute);
}
/// <summary>
/// Gets the data context.
/// </summary>
/// <param name="dataContextPropertyName">Name of the data context property.</param>
/// <returns></returns>
private object GetDataContext(string dataContextPropertyName)
{
PropertyInfo property = _propertyDataContext?.GetType().GetProperty(dataContextPropertyName);
if (property == null) return null;
return property.GetValue(_propertyDataContext, null);
}
/// <summary>
/// Creates the slider data template.
/// </summary>
/// <param name="customUIAttribute">The custom UI attribute.</param>
/// <returns></returns>
private DataTemplate CreateSliderDataTemplate(CustomUIAttribute customUIAttribute)
{
DataTemplate ct = new DataTemplate();
ct.VisualTree = new FrameworkElementFactory(typeof(StackPanel));
ct.VisualTree.SetValue(StackPanel.DataContextProperty, GetDataContext(customUIAttribute.DataContextPropertyName));
FrameworkElementFactory sliderFactory = new FrameworkElementFactory(typeof(Slider));
sliderFactory.SetBinding(Slider.MaximumProperty, new Binding(nameof(SliderUIDataContext.Max)));
sliderFactory.SetBinding(Slider.MinimumProperty, new Binding(nameof(SliderUIDataContext.Min)));
sliderFactory.SetBinding(Slider.SmallChangeProperty, new Binding(nameof(SliderUIDataContext.SmallChange)));
sliderFactory.SetBinding(Slider.LargeChangeProperty, new Binding(nameof(SliderUIDataContext.LargeChange)));
sliderFactory.SetBinding(Slider.ValueProperty, new Binding(nameof(SliderUIDataContext.Value)));
ct.VisualTree.AppendChild(sliderFactory);
FrameworkElementFactory textFacotry = new FrameworkElementFactory(typeof(TextBlock), "TextBlock");
textFacotry.SetValue(TextBlock.TextProperty, new Binding(nameof(SliderUIDataContext.Value)));
//textBoxFactory.AddHandler(TextBox.IsVisibleChanged, new DependencyPropertyChangedEventHandler(SearchBoxVisibleChanged));
ct.VisualTree.AppendChild(textFacotry);
ct.Seal();
return ct;
}
/// <summary>
/// Creates the ComboBox edit template.
/// </summary>
/// <param name="customUIAttribute">The custom UI attribute.</param>
/// <returns></returns>
private DataTemplate CreateComboBoxEditTemplate(CustomUIAttribute customUIAttribute)
{
DataTemplate template = new DataTemplate();
template.VisualTree = new FrameworkElementFactory(typeof(DockPanel));
template.VisualTree.SetValue(DockPanel.DataContextProperty, GetDataContext(customUIAttribute.DataContextPropertyName));
FrameworkElementFactory textFactory = new FrameworkElementFactory(typeof(TextBlock)) ;
textFactory.SetValue(TextBlock.TextProperty, new Binding(nameof(ComboBoxEditDataContext.Name)));
template.VisualTree.AppendChild(textFactory);
FrameworkElementFactory comboBoxEditFactory = new FrameworkElementFactory(typeof(ComboBoxEdit));
comboBoxEditFactory.SetBinding(ComboBoxEdit.ItemsSourceProperty, new Binding(nameof(ComboBoxEditDataContext.ItemSource)));
comboBoxEditFactory.SetBinding(ComboBoxEdit.EditValueProperty, new Binding(nameof(ComboBoxEditDataContext.EditValue)));
comboBoxEditFactory.SetBinding(ComboBoxEdit.SelectedIndexProperty, new Binding(nameof(ComboBoxEditDataContext.SelectedIndex)));
comboBoxEditFactory.SetValue(ComboBoxEdit.ItemTemplateProperty, (DataTemplate)_element.TryFindResource("ComboBoxEditItemTemplate"));
template.VisualTree.AppendChild(comboBoxEditFactory);
template.Seal();
return template;
}
/// <summary>
/// Creates the property definition template.
/// </summary>
/// <param name="customUIAttribute">The custom UI attribute.</param>
/// <returns></returns>
private DataTemplate CreatePropertyDefinitionTemplate(CustomUIAttribute customUIAttribute)
{
DataTemplate dataTemplate = new DataTemplate();
DataTemplate cellTemplate = null;//单元格模板
FrameworkElementFactory factory = new FrameworkElementFactory(typeof(PropertyDefinition));
dataTemplate.VisualTree = factory;
switch (customUIAttribute.CustomUI)
{
case CustomUITypes.Slider:
cellTemplate = CreateSliderDataTemplate(customUIAttribute); break;
//cellTemplate = (DataTemplate)_element.TryFindResource("SliderTemplate");break;
case CustomUITypes.ComboBoxEit:
cellTemplate = CreateComboBoxEditTemplate(customUIAttribute);break;
}
if (cellTemplate != null)
{
factory.SetValue(PropertyDefinition.CellTemplateProperty, cellTemplate);
dataTemplate.Seal();
}
else
{
return null;
}
return dataTemplate;
}
}
}










