DevExpress/DX_WPF

[DX_WPF] PropertyGridControl

딸기우유중독 2023. 6. 20. 17:36

DevExpress Demo 

PropertyGrid 참조

 

PropertyView.xaml

<UserControl x:Class="PMProperties.Views.PropertiesView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
             xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
             xmlns:prism="http://prismlibrary.com/" 
             xmlns:viewModel="PMProperties.ViewModels"
             xmlns:sys="clr-namespace:System;assembly=mscorlib"
             xmlns:dxb="http://schemas.devexpress.com/winfx/2008/xaml/bars"
             xmlns:dxprg="http://schemas.devexpress.com/winfx/2008/xaml/propertygrid"
             xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking"
             prism:ViewModelLocator.AutoWireViewModel="True">

    <!--#region Resources-->
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/PMProperties;component/Resources/ResourceDictionary.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <!--#endregion-->


    <!-- SelectedObject="{Binding Path=SelectedItem.Data}"  -->
    <DockPanel>
        <dxprg:PropertyGridControl
                    x:Name="pPropertyGrid"             
                    ShowProperties="All"
                    SelectedObject="{Binding AppDatadddddddd}"
                    PropertyDefinitionsSource="{Binding Properties}"
                    PropertyDefinitionTemplateSelector="{StaticResource DynamicallyAssignDataEditorsTemplateSelector}"
                    PropertyDefinitionStyle="{StaticResource DynamicallyAssignDataEditorsPropertyDefinitionStyle}"
                    ExpandCategoriesWhenSelectedObjectChanged="True"                           
                    ShowDescriptionIn="ToolTipAndPanel"
                    dxe:ValidationService.AllowAccessibilityAlerts="True">

            <dxmvvm:Interaction.Behaviors>
                <dxmvvm:EventToCommand EventName="SelectionChanged"
                                       Command="{Binding ItemSelectionChangedCommand}"
                                       CommandParameter="{Binding ElementName=RoutedEventArgs}"
                                       PassEventArgsToCommand="True"/>
            </dxmvvm:Interaction.Behaviors>
            
        </dxprg:PropertyGridControl>
    </DockPanel>

</UserControl>

ResorceDictionary.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:PMProperties.Data" 
                    xmlns:dxprg="http://schemas.devexpress.com/winfx/2008/xaml/propertygrid" 
                    xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
                    xmlns:controls="clr-namespace:PMProperties.Controls" >

    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="/PMProperties;component/Resources/DescriptionResource.xaml" />
    </ResourceDictionary.MergedDictionaries>

    <local:DynamicallyAssignDataEditorsTemplateSelector x:Key="DynamicallyAssignDataEditorsTemplateSelector"/>


    <DataTemplate x:Key="descriptionTemplate">
        <RichTextBox x:Name="descriptionRichTextBox" 
                     Foreground="{Binding Path=(TextElement.Foreground), RelativeSource={RelativeSource TemplatedParent}}"  
                     Background="Transparent" 
                     BorderThickness="0" 
                     IsReadOnly="True" 
                     MinWidth="150" 
                     HorizontalContentAlignment="Stretch" 
                     controls:DescriptionAttachedBehavior.Description="{Binding}" 
                     IsTabStop="False" />
    </DataTemplate>

    <Style TargetType="dxprg:PropertyDefinition" x:Key="DynamicallyAssignDataEditorsPropertyDefinitionStyle">
        <Setter Property="Path" Value="{Binding Name}"/>
        <Setter Property="Description" Value="{Binding}"/>
        <Setter Property="DescriptionTemplate" Value="{StaticResource descriptionTemplate}"/>
    </Style>

    <DataTemplate x:Key="Name">
        <dxprg:PropertyDefinition >
            <dxprg:PropertyDefinition.EditSettings>
                <dxe:TextEditSettings MaskType="RegEx"/>
            </dxprg:PropertyDefinition.EditSettings>
        </dxprg:PropertyDefinition>
    </DataTemplate>
    <DataTemplate x:Key="Description">
        <dxprg:PropertyDefinition>
            <!--<dxprg:PropertyDefinition.CellTemplate>
                <DataTemplate>
                    <dxe:TextEdit/>
                </DataTemplate>
            </dxprg:PropertyDefinition.CellTemplate>-->
            <dxprg:PropertyDefinition.EditSettings>
                <dxe:TextEditSettings/>
            </dxprg:PropertyDefinition.EditSettings>
        </dxprg:PropertyDefinition>
    </DataTemplate>
    <DataTemplate x:Key="HyperlinkEdit">
        <dxprg:PropertyDefinition>
            <dxprg:PropertyDefinition.EditSettings>
                <dxe:HyperlinkEditSettings AllowAutoNavigate="True"/>
            </dxprg:PropertyDefinition.EditSettings>
        </dxprg:PropertyDefinition>
    </DataTemplate>

</ResourceDictionary>

DynamicallyAssignDataEditorsTemplateSelector.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Diagnostics;

namespace PMProperties.Data;

//internal class DataTemplateSelector
//{
//}
public class DynamicallyAssignDataEditorsTemplateSelector : DataTemplateSelector
{
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        FrameworkElement element = (FrameworkElement)container;
        //var tName = GetTemplateName((PropertyDescriptor)item);
        DataTemplate resource = element.TryFindResource(GetTemplateName((PropertyDescriptor)item)) as DataTemplate;
        //var retBase = base.SelectTemplate(item, container);
        return resource ?? base.SelectTemplate(item, container);
    }
    public static string GetTemplateName(PropertyDescriptor property)
    {
        var displayAttribute = (DisplayAttribute)property.Attributes[typeof(DisplayAttribute)];
        //var ret = displayAttribute.GetDescription() ?? displayAttribute.GetName();
        return displayAttribute.GetName();

    }
}

DescriptionAttachedBehavior.cs

using PMProperties.Data;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Markup;

namespace PMProperties.Controls;

[ContentProperty("Paragraph")]
public class ParagraphContainer : Control
{
    public Paragraph Paragraph { get; set; }
}
public class DescriptionAttachedBehavior : DependencyObject
{
    static readonly DependencyProperty DescriptionProperty;

    static DescriptionAttachedBehavior()
    {
        DescriptionProperty = DependencyProperty.RegisterAttached("Description", typeof(object), typeof(DescriptionAttachedBehavior), new FrameworkPropertyMetadata(null, DescriptionChanged));
    }
    public static void SetDescription(DependencyObject d, object value)
    {
        d.SetValue(DescriptionProperty, value);
    }
    public static object GetDescription(DependencyObject d)
    {
        return d.GetValue(DescriptionProperty);
    }
    static void DescriptionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var rtb = d as RichTextBox;
        if (rtb == null || rtb.Document == null)
            return;
        rtb.Document.Blocks.Clear();
        var property = e.NewValue as PropertyDescriptor;
        if (property == null)
            return;
        var resName = rtb.TryFindResource(DynamicallyAssignDataEditorsTemplateSelector.GetTemplateName(property) + "Description") as ControlTemplate;
        if (resName == null)
            return;
        ContentControl control = new ContentControl() { Template = rtb.TryFindResource(DynamicallyAssignDataEditorsTemplateSelector.GetTemplateName(property) + "Description") as ControlTemplate};
        control.ApplyTemplate();
        ParagraphContainer container = VisualTreeHelper.GetChild(control, 0) as ParagraphContainer;
        rtb.Document.Blocks.Add(container.Paragraph);
    }
}

DescriptionResource.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:controls="clr-namespace:PMProperties.Controls">

    <ControlTemplate x:Key="HyperlinkEditDescription">
        <controls:ParagraphContainer>
            <Paragraph>
                <Span FontWeight="Bold">HyperlinkEdit</Span> - An editor that presents its contents as a hyperlink.
            </Paragraph>
        </controls:ParagraphContainer>
    </ControlTemplate>
    
    
</ResourceDictionary>
728x90