I want the user to select a directory where a file that I will then generate will be saved. I know that in WPF I should use the OpenFileDialog
from Win32, but unfortunately the dialog requires file(s) to be selected - it stays open if I simply click OK without choosing one. I could "hack up" the functionality by letting the user pick a file and then strip the path to figure out which directory it belongs to but that's unintuitive at best. Has anyone seen this done before?
views:
4455answers:
4
+12
A:
You should use the FolderBrowserDialog class for this. Don't mind that it's in the System.Windows.Forms
namespace.
var dialog = new System.Windows.Forms.FolderBrowserDialog();
System.Windows.Forms.DialogResult result = dialog.ShowDialog();
If you want the window to be modal over some WPF window, see the question How to use a FolderBrowserDialog from a WPF application.
Heinzi
2009-12-17 14:43:45
Thank you, I guess I asked 15 minutes too early.
Alexandra
2009-12-17 14:47:49
+2
A:
Kevin Moore's Bag-o-Tricks include a WPF sample FolderPicker that lets you select a folder.
Manga Lee
2009-12-17 14:49:02
+3
A:
I created a UserControl which is used like this:
<UtilitiesWPF:FolderEntry Text="{Binding Path=LogFolder}" Description="Folder for log files"/>
The xaml source looks like this:
<UserControl x:Class="Utilities.WPF.FolderEntry"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DockPanel>
<Button Margin="0" Padding="0" DockPanel.Dock="Right" Width="Auto" Click="BrowseFolder">...</Button>
<TextBox Height="Auto" HorizontalAlignment="Stretch" DockPanel.Dock="Right"
Text="{Binding Text, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
</DockPanel>
</UserControl>
and the code-behind
public partial class FolderEntry {
public static DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(FolderEntry), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public static DependencyProperty DescriptionProperty = DependencyProperty.Register("Description", typeof(string), typeof(FolderEntry), new PropertyMetadata(null));
public string Text { get { return GetValue(TextProperty) as string; } set { SetValue(TextProperty, value); }}
public string Description { get { return GetValue(DescriptionProperty) as string; } set { SetValue(DescriptionProperty, value); } }
public FolderEntry() { InitializeComponent(); }
private void BrowseFolder(object sender, RoutedEventArgs e) {
using (FolderBrowserDialog dlg = new FolderBrowserDialog()) {
dlg.Description = Description;
dlg.SelectedPath = Text;
dlg.ShowNewFolderButton = true;
DialogResult result = dlg.ShowDialog();
if (result == System.Windows.Forms.DialogResult.OK) {
Text = dlg.SelectedPath;
BindingExpression be = GetBindingExpression(TextProperty);
if (be != null)
be.UpdateSource();
}
}
}
}
adrianm
2009-12-17 15:04:05
+1, nice example on how to write a UserControl. One question: Why do you need `be.UpdateSource`? Shouldn't change notifications be automatic in dependency properties?
Heinzi
2009-12-17 15:14:56
You could specify in the binding when to fire the updates. By default it's on the LostFocus but you can tell it to fire updates on PropertyChanged as well.
Alexandra
2009-12-17 16:52:39
The binding will then also be updated for every keystroke. If the user does some kind of validation on update (e.g. Directory.Exist) it might cause problems.
adrianm
2009-12-18 07:53:53