André Alves de Lima

Talking about Software Development and more…

Utilizando File Pickers em Windows Apps

Quem desenvolve para Windows Forms com certeza sabe que a maneira para possibilitarmos que o usuário selecione arquivos ou pastas é através da utilização das classes OpenFileDialog e FolderBrowserDialog. No WPF também temos o OpenFileDialog (só que localizado em outro namespace – Microsoft.Win32) e, para selecionarmos pastas, a recomendação é que utilizemos o FolderBrowserDialog do Windows Forms. Porém, como você deve ter percebido, tudo mudou no mundo dos Windows Apps (ou Windows Store Apps, ou Metro Style Apps – caramba, será que a Microsoft vai finalmente decidir como ela chamará esse tipo de aplicativo?). Nesse caso, temos que utilizar File Pickers, ou seja, as classes FileOpenPicker e FolderPicker. E é justamente esse o tema do artigo de hoje.

Vamos começar o nosso exemplo, como sempre, criando um projeto do tipo “Blank App“, que se encontra dentro da categoria “Store Apps” / “Windows Apps“. Após o Visual Studio ter criado o projeto, vamos até a MainPage adicionar um Button e um TextBlock dentro do Grid:

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel Margin="50">
            <Button x:Name="SelecionarArquivoButton"
                    Content="Selecionar Arquivo" 
                    Click="SelecionarArquivoButton_Click" />
            <TextBlock x:Name="ResultadoTextBlock" />
        </StackPanel>
    </Grid>

Feito isso, vamos até o code-behind para implementar o código do evento Click do botão (SelecionarArquivoButton_Click):

        private async void SelecionarArquivoButton_Click(object sender, RoutedEventArgs e)
        {
            var fileOpenPicker = new Windows.Storage.Pickers.FileOpenPicker();
            var file = await fileOpenPicker.PickSingleFileAsync();
            if (file != null)
                ResultadoTextBlock.Text = file.Path;
            else
                ResultadoTextBlock.Text = string.Empty;
        }

Veja como é simples selecionar um arquivo em Windows Apps. Primeiro temos que criar uma instância da classe FileOpenPicker. Com ela, chamamos o método PickSingleFileAsync que, como o próprio nome diz, é assíncrono, portanto devemos utilizar a palavra-chave “await” em sua chamada (além disso, repare que tivemos que adicionar a palavra-chave “async” na assinatura do método). O retorno do método PickSingleFileAsync será “null” caso o usuário tenha cancelado a operação, ou um StorageFile caso o usuário tenha de fato selecionado um arquivo. Com o StorageFile em mãos, acessamos o seu caminho (através da propriedade Path) e exibimos o resultado no ResultadoTextBlock.

Simples, não? Pois tente executar a aplicação, clique no botão “Selecionar Arquivo” e veja o resultado:

The FileTypeFilters property must have at least one file type filter specified.

Bang! Exception na cabeça! Mas, por que? Por algum motivo inexplicável, a Microsoft decidiu que você obrigatoriamente tem que especificar um filtro de extensão de arquivo ao exibir FileOpenPickers. Esses filtros devem ser configurados através da propriedade FileTypeFilter.

FileTypeFilter

A propriedade FileTypeFilter serve, como o nome indica, para filtrarmos os tipos de arquivos que serão exibidos no FileOpenPicker. Como mencionei no parágrafo anterior, a Microsoft decidiu que temos que obrigatoriamente especificar um filtro quando exibimos FileOpenPickers. Mas, e se não quisermos filtrar os arquivos a serem exibidos? E se quisermos exibir todos os arquivos no diálogo do FileOpenPicker? Simples! Nesse caso, temos que adicionar um filtro com o tipo de arquivo “*” (asterisco):

            var fileOpenPicker = new Windows.Storage.Pickers.FileOpenPicker();
            fileOpenPicker.FileTypeFilter.Add("*");
            var file = await fileOpenPicker.PickSingleFileAsync();
            if (file != null)
                ResultadoTextBlock.Text = file.Path;
            else
                ResultadoTextBlock.Text = string.Empty;

Se pensarmos no OpenFileDialog do Windows Forms / WPF, tínhamos a propriedade Filter que servia para o mesmo propósito. Porém, no FileOpenPicker das Windows Apps, não podemos adicionar uma descrição à extensão como fazíamos antigamente, já que o FileOpenPicker nem exibe para o usuário quais são os filtros sendo aplicados. Isso, na minha opinião, acaba deixando o usuário confuso. Imagina você tendo que selecionar um arquivo sem saber quais as extensões de arquivos são suportadas? É por essas e outras que muita gente reclama das Windows Apps – praticamente tudo parece um retrocesso ao que temos disponível no desenvolvimento de aplicações desktop. Mas, enfim, isso é um assunto a parte – desculpe o meu desabafo!

Para adicionarmos um filtro de tipo de arquivo, basta utilizarmos a extensão desejada, incluindo o ponto inicial. Por exemplo, para exibirmos somente arquivos do tipo “docx“, basta adicionarmos o filtro “.docx“. Você pode adicionar vários filtros no mesmo FileOpenPicker, como “.doc” e “.docx“:

            fileOpenPicker.FileTypeFilter.Add(".docx");
            fileOpenPicker.FileTypeFilter.Add(".doc");

PickerViewMode

Por padrão, o FileOpenPicker exibe as pastas e arquivos em formato de lista, ou seja, com uma minúscula thumbnail e algumas informações sobre o arquivo, como você pode ver no exemplo abaixo:

Porém, em algumas situações, principalmente para selecionarmos arquivos de mídia (como fotos ou vídeos), essa não é a melhor opção. Nesse caso, seria mais interessante exibirmos as pastas e arquivos em um formato que consigamos ver melhor o conteúdo do arquivo. E acredito que foi pensando nessa situação que a propriedade ViewMode do FileOpenPicker foi criada. Com ela, podemos especificar que as pastas e arquivos sejam exibidos em formato thumbnail:

            fileOpenPicker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail;

Veja a diferença no resultado:

SuggestedStartLocation

Não consegui entender exatamente qual é a pasta que o FileOpenPicker exibe por padrão, mas, através da propriedade SuggestedStartLocation conseguimos especificar a pasta que deverá ser exibida inicialmente pelo FileOpenPicker. Por exemplo, para que o FileOpenPicker seja iniciado na pasta “desktop“, utilize o trecho de código a seguir:

            fileOpenPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Desktop;

Porém, fique atento com essa propriedade, pois, não é possível simplesmente indicar qualquer caminho para a pasta inicial (como conseguíamos fazer anteriormente com o OpenFileDialog). Devido às limitações impostas pelo WinRT e seu modelo de sandbox, só conseguimos selecionar algumas pastas pré-definidas pelo enumerador PickerLocationId:

Selecionando múltiplos arquivos

Para selecionarmos múltiplos arquivos, ao invés de utilizarmos o método PickSingleFileAsync, temos que utilizar o método PickMultipleFilesAsync. Nesse caso, o retorno não será mais um único StorageFile, mas sim, uma lista de StorageFiles. Dessa forma, podemos iterar pelos arquivos e pegar cada um de seus caminhos:

        private async void SelecionarArquivoButton_Click(object sender, RoutedEventArgs e)
        {
            var fileOpenPicker = new Windows.Storage.Pickers.FileOpenPicker();
            fileOpenPicker.FileTypeFilter.Add("*");
            var files = await fileOpenPicker.PickMultipleFilesAsync();
            if (files != null)
            {
                System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
                foreach (var file in files)
                    stringBuilder.AppendLine(file.Path);
                ResultadoTextBlock.Text = stringBuilder.ToString();
            }
            else
                ResultadoTextBlock.Text = string.Empty;
        }

FolderPicker

Até agora vimos como selecionar arquivos em Windows Apps. Mas, e se quisermos selecionar uma pasta ao invés de arquivos? No Windows Forms e WPF utilizaríamos o FolderBrowserDialog. E no WinRT? Qual classe temos que utilizar? Nesse caso, utilizamos a classe FolderPicker.

Essa classe possui a praticamente mesma estrutura da classe FileOpenPicker. A diferença é que, ao invés de chamarmos o método PickSingleFileAsync ou PickMultipleFilesAsync, temos que chamar o método PickSingleFolderAsync. Por mais incrível que pareça, apesar de não surtir nenhum resultado, somos obrigados a configurar um FileTypeFilter, senão receberemos a mesma exceção que recebemos anteriormente com o FileOpenPicker. Na minha opinião (e também na opinião de outras pessoas, veja só), essa foi um erro feio de API que o time do WinRT cometeu. O FileTypeFilter não faz nenhuma diferença ao selecionarmos uma pasta (podemos, por exemplo, configurar o FileTypeFilter como “.doc“, mas, isso não fará nenhuma diferença nas pastas que serão exibidas), então, por que temos que fornecer um FileTypeFilter? Enfim, para contornar esse problema, vamos configurar o FileTypeFilter como “*” (asterisco).

Vamos adicionar mais um botão no nosso StackPanel para fazermos a seleção da pasta:

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel Margin="50">
            <Button x:Name="SelecionarArquivoButton"
                    Content="Selecionar Arquivo" 
                    Click="SelecionarArquivoButton_Click" />
            <Button x:Name="SelecionarPastaButton"
                    Content="Selecionar Pasta"
                    Click="SelecionarPastaButton_Click" />
            <TextBlock x:Name="ResultadoTextBlock" />
        </StackPanel>
    </Grid>

E então, vamos implementar o código para selecionarmos a pasta. Veja só que simples:

        private async void SelecionarPastaButton_Click(object sender, RoutedEventArgs e)
        {
            var folderPicker = new Windows.Storage.Pickers.FolderPicker();
            folderPicker.FileTypeFilter.Add("*");
            var folder = await folderPicker.PickSingleFolderAsync();
            if (folder != null)
                ResultadoTextBlock.Text = folder.Path;
            else
                ResultadoTextBlock.Text = string.Empty;
        }

Concluindo

Se você está acostumado a selecionar arquivos e pastas no WPF e Windows Forms, você sabe exatamente quais classes utilizar e como elas funcionam. Porém, no desenvolvimento de Windows Apps com o WinRT, tudo mudou. Nesse artigo você aprendeu como utilizar as classes FileOpenPicker e FolderPicker para selecionar arquivos e pastas no desenvolvimento de Windows Apps.

Por hoje é só. Espero que você tenha gostado. Não se esqueça de assinar a minha newsletter para ficar por dentro das novidades do meu site (para isso, utilize o formulário logo abaixo)!

Até a próxima!

André Lima

Newsletter do André Lima

* indicates required



Powered by MailChimp

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *