Dizin iletişim kutusunu aç


274

Kullanıcının, daha sonra oluşturacağım bir dosyanın kaydedileceği bir dizin seçmesini istiyorum. Ben WPF OpenFileDialogWin32 kullanmak gerekir biliyorum , ama ne yazık ki iletişim dosya (lar) seçilmesini gerektirir - Ben sadece birini seçmeden Tamam'ı tıklarsanız açık kalır. Ben kullanıcı bir dosya seçmek ve daha sonra hangi dizine ait olduğunu anlamak için yolu şerit izin işlevselliği "kesmek" olabilir ama bu en iyi sezgisel değil. Bunu daha önce gören var mı?




Yanıtlar:


406

Bunun için yerleşik FolderBrowserDialog sınıfını kullanabilirsiniz . System.Windows.FormsAd alanında olduğuna aldırmayın .

using (var dialog = new System.Windows.Forms.FolderBrowserDialog())
{
    System.Windows.Forms.DialogResult result = dialog.ShowDialog();
}

Pencerenin bazı WPF pencerelerinin üzerinde kalıcı olmasını istiyorsanız, WPF uygulamasından FolderBrowserDialog nasıl kullanılır sorusuna bakın .


DÜZENLEME: Düz, çirkin Windows Forms FolderBrowserDialog'dan biraz daha süslü bir şey istiyorsanız, bunun yerine Vista iletişim kutusunu kullanmanıza izin veren bazı alternatifler vardır:

  • Ookii iletişim kutuları (.NET 3.5) gibi üçüncü taraf kitaplıkları
  • Windows API Kod Paketi-Shell :

    using Microsoft.WindowsAPICodePack.Dialogs;
    
    ...
    
    var dialog = new CommonOpenFileDialog();
    dialog.IsFolderPicker = true;
    CommonFileDialogResult result = dialog.ShowDialog();

    Bu iletişim kutusunun Windows Vista'dan daha eski işletim sistemlerinde kullanılamadığını unutmayın, bu yüzden önce kontrol ettiğinizden emin olun CommonFileDialog.IsPlatformSupported.


78
Bunun korkunç bir diyalog olduğunu unutmayın. Bir yolu kopyalayıp yapıştıramazsınız ve favori klasörleri desteklemez. Genel olarak, ben 5 üzerinden 0 vermek ve hiç kimse bunu tavsiye ederim. Windows Vista çok daha iyi bir klasör iletişim kutusu çıkıncaya kadar makul bir alternatif yoktu . Orada iyi ücretsiz kütüphaneler Vista + iyi iletişim ve XP üzerinde kötü olanı gösteririz.
Roman Starkov

70
Yine de, WPF neden harika bir OpenFileDialog sunuyor ancak OpenFolderDialog sunmuyor? Bu biraz garip değil mi? WPF neden burada eksik? WPF'de bu iletişim kutusu için bir sınıf eklemeyi planlıyor musunuz?
Paul-Sebastian Manole

14
FolderBrowserDialog'un tek kullanımlık olduğunu unutmayın.
LosManos

9
Unutmayın ki kullanmak CommonOpenFileDialogiçin WindowsAPICodePackgerekir Install-Package WindowsAPICodePack-Shell. Yanıtta verilen bağlantı bunu listelemiyor.
Nikola Novak

5
"CommonOpenFileDialog türü veya ad alanı bulunamadı". 2017 ve bir klasör
seçemiyorum

46

Bunun gibi kullanılan bir UserControl oluşturdum:

  <UtilitiesWPF:FolderEntry Text="{Binding Path=LogFolder}" Description="Folder for log files"/>

Xaml kaynağı şöyle görünür:

<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>

ve arkadaki kod

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();
            }
        }
    }
 }

1
+1, bir UserControl yazma hakkında güzel bir örnek. Bir soru: Neden ihtiyacınız var be.UpdateSource? Bağımlılık özelliklerinde bildirim değişikliği otomatik olmamalı mı?
Heinzi

4
Güncellemelerin ne zaman tetikleneceğini ciltlemede belirtebilirsiniz. Varsayılan olarak LostFocus'tadır, ancak PropertyChanged'de de güncellemeleri başlatmasını söyleyebilirsiniz.
Alexandra

3
Bağlama daha sonra her tuş vuruşu için güncellenecektir. Kullanıcı güncelleme sırasında bir tür doğrulama yaparsa (örn. Directory.Exist) sorunlara neden olabilir.
adrianm


10

Ookii klasör iletişim kutusu Nuget'te bulunabilir.

PM> Install-Package Ookii.Dialogs

Ve örnek kod aşağıdaki gibidir.

var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog();
if (dialog.ShowDialog(this).GetValueOrDefault())
{
    textBoxFolderPath.Text = dialog.SelectedPath;
}

tnx yolunu kısaydı
ehsan wwe

8

Özel bir iletişim kutusu oluşturmak istemeyen, ancak yine de% 100 WPF yolunu tercih edenler ve ayrı DDL'ler, ek bağımlılıklar veya eski API'ler kullanmak istemeyenler için, Farklı Kaydet iletişim kutusunu kullanarak çok basit bir kesmek buldum.

Direktif kullanmak gerekmez, aşağıdaki kodu kopyalayıp yapıştırabilirsiniz!

Hala çok kullanıcı dostu olmalı ve çoğu insan asla fark etmeyecek.

Fikir, o iletişim kutusunun başlığını değiştirebileceğimiz, dosyaları gizleyebileceğimiz ve sonuçta ortaya çıkan dosya adının etrafında kolayca çalışabileceğimiz gerçeğinden geliyor.

Kesinlikle büyük bir hack, ama belki de işi kullanımınız için iyi yapacak ...

Bu örnekte, ortaya çıkan yolu içerecek bir metin kutusu nesnesi var, ancak ilgili satırları kaldırabilir ve isterseniz bir dönüş değeri kullanabilirsiniz ...

// Create a "Save As" dialog for selecting a directory (HACK)
var dialog = new Microsoft.Win32.SaveFileDialog();
dialog.InitialDirectory = textbox.Text; // Use current value for initial dir
dialog.Title = "Select a Directory"; // instead of default "Save As"
dialog.Filter = "Directory|*.this.directory"; // Prevents displaying files
dialog.FileName = "select"; // Filename will then be "select.this.directory"
if (dialog.ShowDialog() == true) {
    string path = dialog.FileName;
    // Remove fake filename from resulting path
    path = path.Replace("\\select.this.directory", "");
    path = path.Replace(".this.directory", "");
    // If user has changed the filename, create the new directory
    if (!System.IO.Directory.Exists(path)) {
        System.IO.Directory.CreateDirectory(path);
    }
    // Our final value is in path
    textbox.Text = path;
}

Bu hack ile ilgili sadece sorunlar:

  • Onay düğmesi hala "Dizin seç" gibi bir şey yerine "Kaydet" diyor, ancak mayın gibi bir durumda dizin seçimini "çalışır", böylece hala çalışıyor ...
  • Giriş alanı hala "Dizin adı" yerine "Dosya adı" diyor, ancak bir dizinin bir dosya türü olduğunu söyleyebiliriz ...
  • Hala bir "Kayıt türü" açılır listesi var, ancak değeri "Dizin (* .this.directory)" diyor ve kullanıcı bunu başka bir şey için değiştiremiyor, benim için çalışıyor ...

Çoğu insan bunları fark etmeyecek olsa da, eğer microsoft başlarını kıçlarından çıkarırsa kesinlikle resmi bir WPF yolu kullanmayı tercih ederdim, ancak bunu yapana kadar, bu benim geçici çözümüm.


1
Bu harikaydı. Başka hiç kimsenin bunu denememiş gibi görünmesi şaşırdı. NuGet paketi elbette çok daha iyi, ancak NuGet WindowsAPICodePack olmadan, yeni bir paket / referans eklemeden bir klasör seçme yeteneğini HACK etmenin mükemmel bir yoludur.
Kod Acemi

7

Dizin İletişim Kutusu'nun Dizin Yolu'nu alması için önce başvuru System.Windows.Forms ekleyin ve sonra da Çözümle'yi tıklatın ve ardından bu kodu bir düğme tıklatmasına yerleştirin.

    var dialog = new FolderBrowserDialog();
    dialog.ShowDialog();
    folderpathTB.Text = dialog.SelectedPath;

(folderpathTB burada klasör yolunu koymak wana TextBox adı, VEYA u bir dize değişkenine de atayabilirsiniz yani)

    string folder = dialog.SelectedPath;

Ve eğer DosyaAdı / yol almak istiyorsanız, sadece Düğme Tıklamasıyla yapın

    FileDialog fileDialog = new OpenFileDialog();
    fileDialog.ShowDialog();
    folderpathTB.Text = fileDialog.FileName;

(folderpathTB dosya yolu koymak wana nerede TextBox adı, VEYA u da bir dize değişkenine atayabilirsiniz)

Not: Klasör İletişim Kutusu için, System.Windows.Forms.dll projeye eklenmelidir, aksi takdirde çalışmaz.


Cevabınız için teşekkürler, ancak bu yaklaşım yukarıda @Heinzi tarafından zaten açıklanmıştır.
Alexandra

5

Aşağıdaki bağlantıda aşağıdaki kodu buldum ... ve işe yaradı Klasör Seç iletişim kutusu WPF

using Microsoft.WindowsAPICodePack.Dialogs;

var dlg = new CommonOpenFileDialog();
dlg.Title = "My Title";
dlg.IsFolderPicker = true;
dlg.InitialDirectory = currentDirectory;

dlg.AddToMostRecentlyUsedList = false;
dlg.AllowNonFileSystemItems = false;
dlg.DefaultDirectory = currentDirectory;
dlg.EnsureFileExists = true;
dlg.EnsurePathExists = true;
dlg.EnsureReadOnly = false;
dlg.EnsureValidNames = true;
dlg.Multiselect = false;
dlg.ShowPlacesList = true;

if (dlg.ShowDialog() == CommonFileDialogResult.Ok) 
{
  var folder = dlg.FileName;
  // Do something with selected folder string
}

4

İstediğinizi elde etmenin en iyi yolu, diğer insanlar tarafından yapıldığı bir tane kendi wpf tabanlı kontrol oluşturabilir veya kullanmaktır
neden? wpf uygulamasında winforms iletişim kutusunu kullanırken fark edilir bir performans etkisi olacağından (bazı nedenlerden dolayı)
bu projeyi öneriyorum
https://opendialog.codeplex.com/
veya Nuget:

PM> Install-Package OpenDialog

çok MVVM dostu ve winforms iletişim kutusunu sarmalamıyor


3

Nugget paketine eklemenizi öneririm:

  Install-Package OpenDialog

O zaman onu kullanmanın yolu:

    Gat.Controls.OpenDialogView openDialog = new Gat.Controls.OpenDialogView();
    Gat.Controls.OpenDialogViewModel vm = (Gat.Controls.OpenDialogViewModel)openDialog.DataContext;
    vm.IsDirectoryChooser = true;
    vm.Show();

    WPFLabel.Text = vm.SelectedFilePath.ToString();

İşte belgeler: http://opendialog.codeplex.com/documentation

Dosyalar, filtreli dosyalar, klasörler vb. İçin çalışır


2

Ookii VistaFolderBrowserDialogistediğin kişidir .

Klasör Tarayıcısını yalnızca Ooki Dialogs'tan istiyorsanız ve başka bir şey yoksa , Kaynak'ı indirin , Klasör tarayıcısı için ihtiyacınız olan dosyaları seçin (ipucu: 7 dosya) ve .NET 4.5.2'de iyi bir şekilde oluşturulur. Bir referans eklemek zorunda kaldım System.Drawing. Orijinal projedeki referansları kendinizle karşılaştırın.

Hangi dosyaları nasıl buluyorsunuz? Uygulamanızı ve Ookii'yi farklı Visual Studio örneklerinde açın. EkleVistaFolderBrowserDialog.csUygulamanıza ve derleme hataları kaybolana kadar dosya eklemeye devam edin. Bağımlılıkları Ookii projesinde buluyorsunuz - kaynağına kadar takip etmek istediğinizi Control-Click (pun amaçlı).

Bunu yapmak için çok tembelseniz, ihtiyacınız olan dosyalar ...

NativeMethods.cs
SafeHandles.cs
VistaFolderBrowserDialog.cs
\ Interop
   COMGuids.cs
   ErrorHelper.cs
   ShellComInterfaces.cs
   ShellWrapperDefinitions.cs

Dahil VistaFolderBrowserDialog.csetmek istemediğiniz sürece 197 satırını düzenleyinResources.Resx

yeni InvalidOperationException (Properties.Resources.FolderBrowserDialogNoRootFolder) atın;

throw new InvalidOperationException("Unable to retrieve the root folder.");

Telif hakkı bildirimlerini uygulamanıza, license.txt

Kod \Ookii.Dialogs.Wpf.Sample\MainWindow.xaml.cshattı 160-169 kullanabileceğiniz bir örnektir ama kaldırmak gerekir this,dan MessageBox.Show(this,WPF için.

Makinemde Çalışır [TM]


2

Bu eski bir soru olduğunu biliyorum, ama bunu yapmanın basit bir yolu WPF tarafından sağlanan FileDialog seçeneğini kullanmak ve System.IO.Path.GetDirectory (dosya adı) kullanmaktır.


Ancak daha sonra kullanıcıya bir klasör seçmesi söylense bile bir dosya seçmesi gerekir. Deneyimsiz bir kullanıcı bu noktada HelpDesk'i arayabilir ve bir klasör seçmek zorunda kaldığında neden bir dosya seçmesi gerektiğini
sorabilir

0

Bu cevapların hiçbiri benim için işe yaramadı (genellikle bu satırlar boyunca eksik bir referans veya bir şey vardı)

Ancak bu oldukça basit:

WPF uygulamasında FolderBrowserDialog kullanma

Bir referans ekleyin System.Windows.Formsve şu kodu kullanın:

  var dialog = new System.Windows.Forms.FolderBrowserDialog();
  System.Windows.Forms.DialogResult result = dialog.ShowDialog();

Eksik paketleri izlemeye gerek yok. Veya muazzam sınıflar ekleyin

Bu bana yeni bir klasör oluşturmanıza izin veren modern bir klasör seçici veriyor

Diğer makinelere dağıtıldığında etkisini henüz görmedim


0

WPF'de böyle bir şey kullanabilirsiniz. Örnek yöntem oluşturdum. Aşağıdan kontrol edin.

public string getFolderPath()
{
           // Create OpenFileDialog 
           Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();

           OpenFileDialog openFileDialog = new OpenFileDialog();
           openFileDialog.Multiselect = false;

           openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
           if (openFileDialog.ShowDialog() == true)
           {
               System.IO.FileInfo fInfo = new System.IO.FileInfo(openFileDialog.FileName);
               return fInfo.DirectoryName;
           }
           return null;           
       }

1
Bu kullanıcının klasörden bir dosya seçmesini gerektirir. Klasör boşsa, klasörünüzü seçemezsiniz.
Alexandru Dicu

Evet, anlıyorum, bu bir tür çözüm, bu sorun için mükemmel bir çözüm değil.
koberone
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.