WPF File Input Box User Control


One good use-case for creating a user control is a file input text box. This post is based on Adam Nathan’s code in the book WPF 4.5 Unleashed by Sams. This user control combines a TextBox with a Browse Button. The user could type a path and filename in th TextBox or they could click on the Browse button to locate the file. If you use the Browse button, the file name (and path) is automatically placed in the TextBox.

The XAML code is not complex. The Button is docked to the right and the TextBox fills the remaining space except for the margin. When an application consumes this user control they are able to set properties such as BorderBrush, BorderThickness, and Background.

The appearance of FileInputBox depends on its control template, which it inherits from UserControl. The code below goes beyond what is absolutely necessary. It changes the FileName from a plain .NET property to a dependency property. In this way consumers of it can use it as a data-binding target. Adam has also added routed events to the user control. This allows consumers to write triggers based on the routed events exposed.

Below is the code for the file called FileInputBrowseBox.xaml.

<Window x:Class="FileInputBox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:my="clr-namespace:FileInputBox" 
        xmlns:local="clr-namespace:FileInputBox"
        mc:Ignorable="d"
        WindowStartupLocation="CenterScreen"
        Title="FileInputBox" Height="160" Width="500">
    <StackPanel Margin="6">
        <TextBlock>Source: Adam Nathan page 719 - 728.</TextBlock>
        <my:FileInputBrowseBox/>
    </StackPanel>
</Window>

Below is the code-behind.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using Microsoft.Win32;
namespace FileInputBox
{
    [ContentProperty("FileName")]
    public partial class FileInputBrowseBox : UserControl
    {
        public FileInputBrowseBox()
        {
            InitializeComponent();
            theTextBox.TextChanged += new TextChangedEventHandler(OnTextChanged);
        }
        private void theButton_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog d = new OpenFileDialog();
            if (d.ShowDialog() == true) // Result could be true, false, or null
                FileName = d.FileName;
        }
        public string FileName
        {
            get { return (string)GetValue(FileNameProperty); }
            set { SetValue(FileNameProperty, value); }
        }
        private void OnTextChanged(object sender, TextChangedEventArgs e)
        {
            FileName = theTextBox.Text;
            e.Handled = true;
            RoutedEventArgs args = new RoutedEventArgs(FileNameChangedEvent);
            RaiseEvent(args);
        }
        public event RoutedEventHandler FileNameChanged
        {
            add { AddHandler(FileNameChangedEvent, value); }
            remove { RemoveHandler(FileNameChangedEvent, value); }
        }
        public static readonly DependencyProperty FileNameProperty =
           DependencyProperty.Register("FileName", typeof(string), typeof(FileInputBrowseBox));

        public static readonly RoutedEvent FileNameChangedEvent =
            EventManager.RegisterRoutedEvent("FileNameChanged",
            RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(FileInputBrowseBox));

        // code below is from top of page 724 of Adam Nathan book
        protected override void OnContentChanged(object oldContent, object newContent)
        {
            if (oldContent != null)
                throw new InvalidOperationException("You cannot change Content");
        }
    }
}

Consuming the User Control

How you you consume this user control? Check out the next post called WPF Consuming FileInputBox. I made a new WPF project. I added a new user control to the project just as if I was going to write a new user control from scratch. How? Right-click the name of the project in Solution Explorer, click Add, New Item…, User Control and name it FileInputBrowseBox.xaml. All I have to do now is copy and paste the code of the two files from the source project to this new project. The two files are FileInputBrowseBox.xaml and FileInputBrowseBox.xaml.cs.