How to: Create a Dialog Box Property Value Editor

The following code example shows how to implement a custom dialog box property value editor for the WPF Designer for Visual Studio. For a complete solution, see the Dialog Property Value Editor sample from the WPF Designer Extensibility Samples site. 

Example

This topic shows how to create a dialog box property value editor that displays an open file dialog box when a custom FileName property is clicked in the Properties window.

using System;
using System.ComponentModel;
using System.Windows.Controls;
using System.Windows;

namespace CustomControlLibrary
{
    public partial class DemoControl : UserControl
    {
        public DemoControl()
        {
            InitializeComponent();
        }

        public static readonly DependencyProperty FileNameProperty = DependencyProperty.Register(
            "FileName", 
            typeof(string), 
            typeof(DemoControl), 
            new PropertyMetadata("File name not set."));

        public string FileName
        {
            get
            {
                return (string)this.GetValue(FileNameProperty);
            }

            set
            {
                this.SetValue(FileNameProperty, value);
            }
        }
    }
}
<ResourceDictionary xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:PropertyEditing="clr-namespace:Microsoft.Windows.Design.PropertyEditing;assembly=Microsoft.Windows.Design.Interaction"
                    xmlns:Local="clr-namespace:CustomControlLibrary.Design"
                    x:Class="CustomControlLibrary.Design.EditorResources">

    <DataTemplate x:Key="FileBrowserInlineEditorTemplate">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <TextBox Grid.Column="0" Text="{Binding StringValue}"/>
            <PropertyEditing:EditModeSwitchButton Grid.Column="1"/>
        </Grid>
    </DataTemplate>

</ResourceDictionary>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CustomControlLibrary.Design
{
    using System.Windows;
    public partial class EditorResources : ResourceDictionary
    {
        public EditorResources()
            : base()
        {
            InitializeComponent();
        }
    }
}
using System;
using System.ComponentModel;
using System.Windows;
using Microsoft.Windows.Design.Metadata;
using Microsoft.Windows.Design.PropertyEditing;
using Microsoft.Win32;

namespace CustomControlLibrary.Design
{
    public class FileBrowserDialogPropertyValueEditor : DialogPropertyValueEditor
    {
        private EditorResources res = new EditorResources();

        public FileBrowserDialogPropertyValueEditor()
        {
            this.InlineEditorTemplate = res["FileBrowserInlineEditorTemplate"] as DataTemplate;
        }

        public override void ShowDialog(
            PropertyValue propertyValue,
            IInputElement commandSource)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Multiselect = false;

            if (ofd.ShowDialog() == true)
            {
                propertyValue.StringValue = ofd.FileName;
            }
        }
    }
}
using System;
using System.ComponentModel;
using System.Windows;
using Microsoft.Windows.Design.Metadata;
using Microsoft.Windows.Design.PropertyEditing;

// The ProvideMetadata assembly-level attribute indicates to designers
// that this assembly contains a class that provides an attribute table. 
[assembly: ProvideMetadata(typeof(CustomControlLibrary.Design.Metadata))]
namespace CustomControlLibrary.Design
{
    // Container for any general design-time metadata to initialize.
    // Designers look for a type in the design-time assembly that 
    // implements IProvideAttributeTable. If found, designers instantiate 
    // this class and access its AttributeTable property automatically.
    internal class Metadata : IProvideAttributeTable 
    {
        // Accessed by the designer to register any design-time metadata.
        public AttributeTable AttributeTable
        {
            get 
            {
                AttributeTableBuilder builder = new AttributeTableBuilder();

                builder.AddCustomAttributes
                    (typeof(CustomControlLibrary.DemoControl),
                    "FileName",
                    PropertyValueEditor.CreateEditorAttribute(
                        typeof(FileBrowserDialogPropertyValueEditor)));

                return builder.CreateTable();
            }
        }
    }
}
<Window x:Class="WpfApplication1.MainWindow"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ccl="clr-namespace:CustomControlLibrary;assembly=CustomControlLibrary"
    Title="MainWindow" Height="300" Width="300">
    <Grid>
        <ccl:DemoControl FileName="" />
    </Grid>
</Window>

Compiling the Code

Compile the previous example code in three separate assemblies.

Compiling the Custom Control

  1. In Visual Studio, create a new WPF User Control Library project in C# named CustomControlLibrary.

  2. Change all occurrences of "UserControl1" to "DemoControl".

  3. Replace the existing code in the DemoControl class with the code listed earlier.

  4. Build the solution.

Compiling the Custom Dialog Box Property Value Editor

  1. In Visual Studio, add a new WPF User Control Library project named CustomControlLibrary.Design to the solution.

  2. Set the project's output path to "..\CustomControlLibrary\bin\Debug\".

  3. Delete UserControl1.xaml and UserControl1.xaml.cs from the project.

  4. Add references to the following assemblies.

    • Microsoft.Windows.Design.Extensibility

    • Microsoft.Windows.Design.Interaction

  5. Add a reference to the CustomControlLibrary project.

  6. Add a resource dictionary named EditorResources to the project.

  7. Replace the existing XAML in EditorResources.xaml with the XAML listed earlier.

  8. Add a new class named EditorResources to the project.

  9. Replace the existing code in the EditorResources with the code listed earlier.

  10. Add a new class named FileBrowserDialogPropertyValueEditor to the project.

  11. Replace the existing code in the FileBrowserDialogPropertyValueEditor class with the code listed earlier.

  12. Add a new class named Metadata to the project.

  13. Replace the existing code in the Metadata class with the code listed earlier.

  14. Build the solution.

Compiling the Test Application

  1. In Visual Studio, add a new WPF Application project to the solution.

  2. Add a reference to the CustomControlLibrary assembly or project.

  3. In XAML view for MainWindow.xaml, replace the existing XAML with the XAML listed earlier.

  4. In MainWindow.xaml.cs, comment out the call to InitializeComponent.

  5. Rebuild the solution.

  6. In Design view, click the DemoControl to select it. You might have to click the Information bar at the top of the designer to reload the view.

  7. In the Properties window, click the button next to the FileName property.

    The Open dialog box appears.

  8. Navigate to a file and click Open.

    The file name is displayed in the FileName property of the Properties window and the FileName property is assigned in XAML view.

See Also

Reference

ItemPolicy

PrimarySelectionPolicy

Other Resources

Advanced Extensibility Concepts

WPF Designer Extensibility

WPF Designer Extensibility Samples