Search This Blog

Browse For file or directory custom control in C#

I had often to create a browse button along with a text box that will display the access path to a folder or a file on File System, So I have decided to create a composite control that will have this feature built in.

Here is a snapshot of the control as run-time.


The control is simply a wrapper for both FolderBrowserDialog and OpenFileDialog classes.

Here is the code:

[DefaultProperty("Text")]
[DefaultEvent("SelectedPathChanged")]
public partial class BrowseButton : UserControl
{   
     /// 
    /// The event will be fired whenever end users change the selected folder of file.
    /// 
    public event EventHandler SelectedPathChanged;





     /// 
    /// The event will be fired just before accepting the file or folders end user selected. we give  
    /// developer the chance to catch this event and cancel the selection if necessary.
    /// 

    public event EventHandler<SelectedPathCancelEventArgs> SelectedPathChanging;
    private event EventHandler BrowseTypeChanged;

    ///
    /// Describes and determines how to respond the Browse button click.
    ///
    public enum BrowseTarget
    {
        ///
        /// Indicates that selection should be performed against Files.
        ///
        File,
        ///
        /// Indicates that selection should be performed against Directories.
        ///
        Directory
    }

    public BrowseButton()
    {
        InitializeComponent();
        BrowseTypeChanged += new EventHandler(BrowseButton_BrowseTypeChanged);
        Text = "Browse";
    }





    /// if the user has Set BrowseType property to File and MultiFileSelect is true than set textbox MultiLine property to true as well, so we can display multiple selections.
    void BrowseButton_BrowseTypeChanged(object sender, EventArgs e)

    {
        switch (BrowseType)
        {
            case BrowseTarget.File:
                txtPath.Multiline = MultiFileSelect;
                break;
            case BrowseTarget.Directory:
                txtPath.Multiline = false;
                break;
            default:
                break;
        }
    }
Here is the effect at runtime:


    [DefaultValue("")]
    [Category("BrowseButton")]
    [Description("The file filters to display in the dialog box, for example, \"C# files|*.cs|All files|*.*\".")]
    public string FileFilter
    {
        get
        {
            return ofd.Filter;
        }
        set
        {
            ofd.Filter = value;
        }
    }

    [Editor("System.Windows.Forms.Design.SelectedPathEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
        typeof(UITypeEditor))]
    [Description("The path of the folder first selected in the dialog or the last one selected by the user.")]
    [Category("BrowseButton")]
    public string InitialPath
    {
        get
        {
            string val = "";
            switch (target)
            {
                case BrowseTarget.File:
                    val = ofd.InitialDirectory;
                    break;

                    case BrowseTarget.Directory:
                    val = fbd.SelectedPath;
                    break;

                default:
                    break;
            }
            return val;
        }
        set
        {
            ofd.InitialDirectory = value;
            fbd.SelectedPath = value;
        }
    }


    [DefaultValue("")]
    [Description("Gets or sets the selected path")]
    [Category("BrowseButton")]
    public string SelectedPath {
        get
        {
            return txtPath.Text;
        }
        set
        {
            if (SelectedPath != value)
            {
                SelectedPathCancelEventArgs e = new SelectedPathCancelEventArgs(value);
                /// Fire selection changing event.
                OnSelectedPathChanging(this, e);
                /// if cancel is not requested than apply the new value.
                if(!e.Cancel)
                    /// this wil trigger SelectedPathChanged event.
                    txtPath.Text = value;
            }
        }
    }

    private BrowseTarget target = BrowseTarget.File;
    [DefaultValue(BrowseTarget.File)]
    [Description("Specify the target of the browse, either a file or a directory")]
    [Category("BrowseButton")]
    public BrowseTarget BrowseType
    {
        get
        {
            return target;
        }
        set
        {
            if (target != value)
            {
                target = value;
                if (BrowseTypeChanged != null)
                {
                    BrowseTypeChanged(this, EventArgs.Empty);
                }
            }


        }
    }
     /// This is the handler for Click event on browse button. FolderBrowserDialog or OpenFileFDialog will be shown based on the value of target.
    private void btnBrowse_Click(object sender, EventArgs e)
    {
        switch (target)
        {
            case BrowseTarget.File:
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    if (ofd.Multiselect)
                    {
                        StringBuilder builder = new StringBuilder();
                        foreach (string fileName in ofd.FileNames)
                        {
                            builder.AppendLine(fileName);
                        }
                        SelectedPath = builder.ToString();
                    }
                    else
                        SelectedPath = ofd.FileName;
                }
                break;
            case BrowseTarget.Directory:
                if (fbd.ShowDialog() == DialogResult.OK)
                {
                    SelectedPath = fbd.SelectedPath;
                }
                break;
            default:
                break;
        }
    }

Here is what is shown in case if target = Directory.

and in case target = File:



    private void txtPath_TextChanged(object sender, EventArgs e)
    {
        OnSelectedPathChanged(this, e);
    }

    protected virtual void OnSelectedPathChanged(object sender, EventArgs e)
    {
        if (SelectedPathChanged != null)
            SelectedPathChanged(sender, e);
    }

    protected virtual void OnSelectedPathChanging(object sender, SelectedPathCancelEventArgs e)
    {
        if (SelectedPathChanging != null)
            SelectedPathChanging(sender, e);
    }

    [Description("The text associated with the control")]
    [Category("BrowseButton")]
    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    public override string Text
    {
        get
        {
            return btnBrowse.Text;
        }
        set
        {
            btnBrowse.Text = value;
        }
    }
    // When this property is set to true, the Text box field can not be edited, otherwise yes.
    [DefaultValue(false)]
    [Description("Controls whether the text in the edit control can be changed or not.")]
    public bool ReadOnly
    {
        get
        {
            return txtPath.ReadOnly;
        }
        set
        {
            txtPath.ReadOnly = value;
        }       
    }

here are snapshots for both cases:
ReadOnly = true

and ReadOnly = false


    [Description("Controls whether multiple files can be selected in the dialog. This property has an effect when BrowseType = BrowseTarget.File")]
    [DefaultValue(false)]
    [Category("BrowseButton")]
    public bool MultiFileSelect
    {
        get
        {
            return ofd.Multiselect;
        }
        set
        {
            ofd.Multiselect = value;
            if (target == BrowseTarget.File)
            {
                txtPath.Multiline = value;
            }
        }
    }

When MultiFileSelect = true and BrowseType = File than TextBox Height changes to fit the control area.

if MultiSelect = false than Textbox will get its standard appearance.


}

public class SelectedPathCancelEventArgs : CancelEventArgs
{

    public SelectedPathCancelEventArgs(string newPath)
        :base()
    {
        this.newPath = newPath;
    }
    private string newPath = null;
    public string NewPath
    {
        get
        {
            return newPath;
        }
    }
}


You can find here a list of book references:
Pro .NET 2.0 Windows Forms and Custom Controls in C#

No comments:

Post a Comment