Skip to content

Commit

Permalink
Merge pull request #62 from lozo2010/master
Browse files Browse the repository at this point in the history
Add support for multiselect folder browser
  • Loading branch information
augustoproiete authored Nov 11, 2021
2 parents 15b96b9 + de0e029 commit 1fa2a39
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 12 deletions.
1 change: 1 addition & 0 deletions sample/Ookii.Dialogs.Wpf.Sample/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<ComboBoxItem>Progress Dialog</ComboBoxItem>
<ComboBoxItem>Credential Dialog</ComboBoxItem>
<ComboBoxItem>Vista-style Folder Browser Dialog</ComboBoxItem>
<ComboBoxItem>Vista-style Folder Browser Dialog (Select Multiple)</ComboBoxItem>
<ComboBoxItem>Vista-style Open File Dialog</ComboBoxItem>
<ComboBoxItem>Vista-style Save File Dialog</ComboBoxItem>
</ComboBox.Items>
Expand Down
46 changes: 41 additions & 5 deletions sample/Ookii.Dialogs.Wpf.Sample/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,12 @@ private void _showDialogButton_Click(object sender, RoutedEventArgs e)
ShowFolderBrowserDialog();
break;
case 5:
ShowOpenFileDialog();
ShowFolderBrowserDialogSelectMultiple();
break;
case 6:
ShowOpenFileDialog();
break;
case 7:
ShowSaveFileDialog();
break;
}
Expand Down Expand Up @@ -162,13 +165,46 @@ private void ShowCredentialDialog()

private void ShowFolderBrowserDialog()
{
VistaFolderBrowserDialog dialog = new VistaFolderBrowserDialog();
var dialog = new VistaFolderBrowserDialog();
dialog.Description = "Please select a folder.";
dialog.UseDescriptionForTitle = true; // This applies to the Vista style dialog only, not the old dialog.
if( !VistaFolderBrowserDialog.IsVistaFolderDialogSupported )

if (!VistaFolderBrowserDialog.IsVistaFolderDialogSupported)
{
MessageBox.Show(this, "Because you are not using Windows Vista or later, the regular folder browser dialog will be used. Please use Windows Vista to see the new dialog.", "Sample folder browser dialog");
if( (bool)dialog.ShowDialog(this) )
MessageBox.Show(this, "The selected folder was: " + dialog.SelectedPath, "Sample folder browser dialog");
}

if ((bool)dialog.ShowDialog(this))
{
MessageBox.Show(this, $"The selected folder was:{Environment.NewLine}{dialog.SelectedPath}", "Sample folder browser dialog");
}
}

private void ShowFolderBrowserDialogSelectMultiple()
{
var dialog = new VistaFolderBrowserDialog();
dialog.Multiselect = true;
dialog.Description = "Please select a folder.";
dialog.UseDescriptionForTitle = true; // This applies to the Vista style dialog only, not the old dialog.

if (!VistaFolderBrowserDialog.IsVistaFolderDialogSupported)
{
MessageBox.Show(this, "Because you are not using Windows Vista or later, the regular folder browser dialog will be used. Please use Windows Vista to see the new dialog.", "Sample folder browser dialog");
}

if ((bool)dialog.ShowDialog(this))
{
var selectedPaths = dialog.SelectedPaths;

if (selectedPaths.Length == 1)
{
MessageBox.Show(this, $"The selected folder was:{Environment.NewLine}{selectedPaths[0]}", "Sample folder browser dialog");
}
else
{
MessageBox.Show(this, $"The selected folders were:{Environment.NewLine}{string.Join(Environment.NewLine, selectedPaths)}", "Sample folder browser dialog");
}
}
}

private void ShowOpenFileDialog()
Expand Down
122 changes: 115 additions & 7 deletions src/Ookii.Dialogs.Wpf/VistaFolderBrowserDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using System.Windows.Interop;
using System.Windows;
using System.Runtime.InteropServices;
using System.Linq;

namespace Ookii.Dialogs.Wpf
{
Expand All @@ -40,6 +41,8 @@ public sealed class VistaFolderBrowserDialog
{
private string _description;
private string _selectedPath;
private NativeMethods.FOS _options;
private string[] _selectedPaths;

/// <summary>
/// Creates a new instance of the <see cref="VistaFolderBrowserDialog" /> class.
Expand Down Expand Up @@ -108,8 +111,14 @@ public string SelectedPath
{
get
{
return _selectedPath ?? string.Empty;
var selectedPath =
_selectedPath ??
_selectedPaths?.FirstOrDefault() ??
string.Empty;

return selectedPath;
}

set
{
_selectedPath = value;
Expand All @@ -135,6 +144,63 @@ public string SelectedPath
[Category("Folder Browsing"), DefaultValue(false), Description("A value that indicates whether to use the value of the Description property as the dialog title for Vista style dialogs. This property has no effect on old style dialogs.")]
public bool UseDescriptionForTitle { get; set; }

/// <summary>
/// Gets or sets a value indicating whether the dialog box allows multiple folder to be selected.
/// </summary>
/// <value>
/// <see langword="true" /> if the dialog box allows multiple folder to be selected together or concurrently; otherwise, <see langword="false" />.
/// The default value is <see langword="false" />.
/// </value>
[Description("A value indicating whether the dialog box allows multiple folders to be selected."), DefaultValue(false), Category("Behavior")]
public bool Multiselect
{
get
{
return HasOption(NativeMethods.FOS.FOS_ALLOWMULTISELECT);
}

set
{
SetOption(NativeMethods.FOS.FOS_ALLOWMULTISELECT, value);
}
}

/// <summary>
/// Gets the folder paths of all selected folder in the dialog box.
/// </summary>
/// <value>
/// An array of type <see cref="string"/>, containing the folder paths of all selected folder in the dialog box.
/// </value>
[Description("The folder path of all selected folder in the dialog box."), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string[] SelectedPaths
{
get
{
var selectedPaths = _selectedPaths;

if (selectedPaths is null)
{
var selectedPath = _selectedPath;
if (string.IsNullOrWhiteSpace(selectedPath))
{
return new string[0];
}
else
{
return new[] { selectedPath };
}
}

return (string[])selectedPaths.Clone();
}

set
{
_selectedPaths = value;
}
}


#endregion

#region Public Methods
Expand All @@ -149,6 +215,8 @@ public void Reset()
_selectedPath = string.Empty;
RootFolder = Environment.SpecialFolder.Desktop;
ShowNewFolderButton = true;
_selectedPaths = null;
_options = 0;
}

/// <summary>
Expand Down Expand Up @@ -184,6 +252,27 @@ public void Reset()

#endregion

#region Internal Methods

internal void SetOption(NativeMethods.FOS option, bool value)
{
if (value)
{
_options |= option;
}
else
{
_options &= ~option;
}
}

internal bool HasOption(NativeMethods.FOS option)
{
return (_options & option) != 0;
}

#endregion

#region Private Methods

private bool RunDialog(IntPtr owner)
Expand Down Expand Up @@ -275,9 +364,9 @@ private void SetDialogProperties(Ookii.Dialogs.Wpf.Interop.IFileDialog dialog)
}
}

dialog.SetOptions(NativeMethods.FOS.FOS_PICKFOLDERS | NativeMethods.FOS.FOS_FORCEFILESYSTEM | NativeMethods.FOS.FOS_FILEMUSTEXIST);
dialog.SetOptions(NativeMethods.FOS.FOS_PICKFOLDERS | NativeMethods.FOS.FOS_FORCEFILESYSTEM | NativeMethods.FOS.FOS_FILEMUSTEXIST | _options);

if( !string.IsNullOrEmpty(_selectedPath) )
if ( !string.IsNullOrEmpty(_selectedPath) )
{
string parent = Path.GetDirectoryName(_selectedPath);
if( parent == null || !Directory.Exists(parent) )
Expand All @@ -293,11 +382,30 @@ private void SetDialogProperties(Ookii.Dialogs.Wpf.Interop.IFileDialog dialog)
}
}

private void GetResult(Ookii.Dialogs.Wpf.Interop.IFileDialog dialog)
private void GetResult(IFileDialog dialog)
{
Ookii.Dialogs.Wpf.Interop.IShellItem item;
dialog.GetResult(out item);
item.GetDisplayName(NativeMethods.SIGDN.SIGDN_FILESYSPATH, out _selectedPath);
if (Multiselect)
{
((IFileOpenDialog)dialog).GetResults(out IShellItemArray results);

results.GetCount(out uint count);
string[] folderPaths = new string[count];

for (uint x = 0; x < count; ++x)
{
results.GetItemAt(x, out IShellItem item);
item.GetDisplayName(NativeMethods.SIGDN.SIGDN_FILESYSPATH, out string name);

folderPaths[x] = name;
}

SelectedPaths = folderPaths;
}
else
{
dialog.GetResult(out IShellItem item);
item.GetDisplayName(NativeMethods.SIGDN.SIGDN_FILESYSPATH, out _selectedPath);
}
}

private int BrowseCallbackProc(IntPtr hwnd, NativeMethods.FolderBrowserDialogMessage msg, IntPtr lParam, IntPtr wParam)
Expand Down

0 comments on commit 1fa2a39

Please sign in to comment.