PropertyGrid是一个很强大的控件,使用该控件做属性设置面板的一个好处就是你只需要专注于代码而无需关注UI的呈现,PropertyGrid会默认根据变量类型选择合适的控件显示。但是这也带来了一个问题,就是控件的使用变得不是特别灵活,主要表现在你无法根据你的需求很好的选择控件,比如当你需要用Slider控件来设置int型变量时,PropertyGrid默认的模板选择器是不支持的。网上找了许多资料基本都是介绍WinForm的实现方式,主要用到了IWindowFromService这个接口,并未找到合适的适合WPF的Demo,后来在参考了DEVExpress的官方Demo之后我做了一个基于WPF和DEV 16.2的PropertyGrid Demo,基本实现了上述功能。
为了实现这一点,需要自定义一个DataTemplateSeletor类,这也是本文的核心代码。
1.创建一个CustomPropertyGrid自定义控件:
<UserControl x:Class="PropertyGridDemo.PropertyGridControl.CustomPropertyGrid" xmlns="" xmlns:x="" xmlns:d="" xmlns:dxprg="" xmlns:local="clr-namespace:PropertyGridDemo.PropertyGridControl" xmlns:mc="" d:DesignHeight="300" d:DesignWidth="300" mc:Ignorable="d"> <UserControl.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <!-- 资源字典 --> <ResourceDictionary Source="http://www.jsgho.com/help/PropertyGridControl/DynamicallyAssignDataEditorsResources.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </UserControl.Resources> <Grid> <!-- PropertyDefinitionStyle:定义属性描述的风格模板 --> <!-- PropertyDefinitionTemplateSelector:定义一个模板选择器,对应一个继承自DataTemplateSelector的类 --> <!-- PropertyDefinitionsSource:定义一个获取数据属性集合的类,对应一个自定义类(本Demo中对应DataEditorsViewModel) --> <dxprg:PropertyGridControl x:Name="PropertyGridControl" Margin="24" DataContextChanged="PropertyGridControl_DataContextChanged" ExpandCategoriesWhenSelectedObjectChanged="True" PropertyDefinitionStyle="{StaticResource DynamicallyAssignDataEditorsPropertyDefinitionStyle}" PropertyDefinitionTemplateSelector="{StaticResource DynamicallyAssignDataEditorsTemplateSelector}" PropertyDefinitionsSource="{Binding Path=Properties, Source={StaticResource DemoDataProvider}}" ShowCategories="True" ShowDescriptionIn="Panel" /> </Grid> </UserControl>
该控件使用的资源字典如下:
<ResourceDictionary xmlns="" xmlns:x="" xmlns:d="" xmlns:dxe="" xmlns:dxg="" xmlns:dxprg="" xmlns:local="clr-namespace:PropertyGridDemo.PropertyGridControl" xmlns:mc="" mc:Ignorable="d"> <local:DynamicallyAssignDataEditorsTemplateSelector x:Key="DynamicallyAssignDataEditorsTemplateSelector" /> <local:DataEditorsViewModel x:Key="DemoDataProvider" /> <DataTemplate x:Key="DescriptionTemplate"> <RichTextBox x:Name="descriptionRichTextBox" MinWidth="150" HorizontalContentAlignment="Stretch" Background="Transparent" BorderThickness="0" Foreground="{Binding Path=(TextElement.Foreground), RelativeSource={RelativeSource TemplatedParent}}" IsReadonly="True" IsTabStop="False" /> </DataTemplate> <DataTemplate x:Key="descriptionTemplate"> <RichTextBox x:Name="descriptionRichTextBox" MinWidth="150" HorizontalContentAlignment="Stretch" Background="Transparent" BorderThickness="0" Foreground="{Binding Path=(TextElement.Foreground), RelativeSource={RelativeSource TemplatedParent}}" IsReadonly="True" IsTabStop="False" /> </DataTemplate> <!-- 设置控件的全局样式和数据绑定 --> <Style x:Key="DynamicallyAssignDataEditorsPropertyDefinitionStyle" TargetType="dxprg:PropertyDefinition"> <Setter Property="Path" Value="{Binding Name}" /> <!--<Setter Property="Header" Value="{Binding Converter={StaticResource PropertyDescriptorToDisplayNameConverter}}"/>--> <Setter Property="Description" Value="{Binding}" /> <Setter Property="DescriptionTemplate" Value="{StaticResource descriptionTemplate}" /> </Style> <Style x:Key="DescriptionContainerStyle" TargetType="dxprg:PropertyDescriptionPresenterControl"> <Setter Property="ShowSelectedRowHeader" Value="False" /> <Setter Property="MinHeight" Value="70" /> </Style> <Style TargetType="Slider"> <Setter Property="Margin" Value="2" /> </Style> <Style TargetType="dxe:ComboBoxEdit"> <Setter Property="IsTextEditable" Value="False" /> <Setter Property="ApplyItemTemplateToSelectedItem" Value="True" /> <Setter Property="Margin" Value="2" /> </Style> <!-- 测试直接从DataTemplate获取控件 --> <DataTemplate x:Key="SliderTemplate" DataType="local:SliderExtend"> <!--<dxprg:PropertyDefinition> <dxprg:PropertyDefinition.CellTemplate>--> <!--<DataTemplate>--> <StackPanel x:Name="Root"> <Slider Maximum="{Binding Path=Max}" Minimum="{Binding Path=Min}" Value="{Binding Path=Value}" /> <TextBlock Text="{Binding Path=Value}" /> </StackPanel> <!--</DataTemplate>--> <!--</dxprg:PropertyDefinition.CellTemplate> </dxprg:PropertyDefinition>--> </DataTemplate> <DataTemplate x:Key="ComboBoxEditItemTemplate" DataType="Tuple"> <TextBlock Height="20" Margin="5,3,0,0" VerticalAlignment="Center" Text="{Binding Item1}" /> </DataTemplate> </ResourceDictionary>
2.编写对应的模板选择类 DynamicallyAssignDataEditorsTemplateSelector:
- 下一篇: Excel2007怎么冻结窗口
- 上一篇: cbox打不开终极解决方法