Проекты
December 17, 2018

Программа для добавления/удаления строки к именам файлов в папке. Часть 1.

Как-то раз столкнулся с такой проблемой. Понадобилось добавить к именам всех файлов в папке одну и ту же строку, но так как файлов было очень много (10-ки тысяч) вручную это сделать не представлялось возможным. Вот и пришла в голову идея написать маленькую программу, которая добавляет строку к имени файла и может удалять символы, начиная с введенного индекса.

Программу писал на основе технологии WPF. Для того чтобы потренироваться с применением архитектурных паттернов, принял решение реализовать проект с использованием MVVM (о нем расскажу в отдельной статье). Unit тестирование не добавлял, в случае развития проекта (есть идеи добавить еще какой-нибудь функционал) добавлю.

Создание проекта и определение структуры.

В VS создаем новый проект "Приложение WPF". Через «Диспетчер пакетов NuGet» устанавливаем библиотеку MVVM Ligth (хорошая библиотека, которая создает уже определенную логику и макет проекта). Она нам создаст папку ViewModel, в которой находятся два класса ViewModelLocator (помогает с Binding’ом данных и создает экземпляр класса ViewModel) и MainViewModel (в нем содержится логика для представления MainWindow), они нам нужны, для того чтобы развязать представление от бизнес логики приложения. Добавим так же папки Views и Helpers, в первую переместим все файлы представлений (он у нас пока один), а во второй будут храниться классы, которые помогут отправлять Messages из ViewModel во View.

Таким образом, мы реализовали структуру проекта (в простом варианте, без классов моделей).

Создание представления.

Графический интерфейс у нас будет состоять из двух вкладок:

• добавление строк к имени файла

• удаление символов из имени файла

На рисунке ниже показано, как выглядит первая вкладка

На ней есть поле для ввода пути до папки, в которой будут переименовываться файлы, а справа кнопка для вызова диалогового окна выбора папки.

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition Width="30"/>
    </Grid.ColumnDefinitions>
    <TextBox Grid.Column="0" Name="PathToFolderAddString_tb" 
             Text="{Binding PathToFilesForAddString_Renamer, 
             Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
    <Button Grid.Column="1" Name="BrowseFolderAddString_btn" Content="..." 
             Click="BrowseFolderAddString_btn_OnClick"/>
</Grid>

Пришлось использовать класс FolderBrowserDialog из библиотеки System.Windows.Forms, так как в WPF нет встроенного класса с таким диалоговым окном.

Код для метода Click кнопки BrowseFolderAddString_btn.

private void BrowseFolderAddString_btn_OnClick(object sender, RoutedEventArgs e)
    {
      FolderBrowserDialog fbd = new FolderBrowserDialog();
      fbd.Description = "Выберите путь до папки с файлами";
      if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
      {
        PathToFolderAddString_tb.Text = fbd.SelectedPath;
      }
    }

Ниже расположены три TextBox’а, в которые нужно ввести текст для добавления.

<Label Content="Добавить текст до:"/>
<TextBox Name="AddTextBefore_tb" Text="{Binding StringBeforeFileName_Renamer, 
         UpdateSourceTrigger=PropertyChanged}"/>
<Label Content="Добавить текст после:"/>
<TextBox Name="AddTextAfter_tb" Text="{Binding StringAfterFileName_Renamer,
         UpdateSourceTrigger=PropertyChanged}"/>
<StackPanel Orientation="Horizontal">
<Label Content="Вставить текст на позицию: "/>
<xctk:IntegerUpDown Minimum="0" Margin="10 5 0 5" Text="{Binding InputPosition_Renamer,
         UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
<TextBox Name="InsertTextOnPosition_td" Text="{Binding InsertTextOnPosition_Renamer,
         UpdateSourceTrigger=PropertyChanged}"/>

Справа Button для выполнения переименования и CheckBox, который запускает непрерывное сканирование на появление событий связанных с выбранной папкой (такие события как: добавление, удаление, переименование файлов).

<GroupBox Header="Запуск переименовывания" Grid.Column="1" Margin="5" Padding="5">
     <StackPanel Margin="10">
         <Button Name="RenameFilesOneTime_btn" Command="{Binding RenameFiles_Renaimer_Command}" 
                 Content="Переименовать файлы" />
         <CheckBox Margin="0 10 0 10" IsChecked="{Binding AutoWatchingForFolder,
                 UpdateSourceTrigger=PropertyChanged}">
         <TextBlock Text="Автоматически переименовывать файлы при появлении в папке" 
                 TextWrapping="Wrap"/>
             <i:Interaction.Triggers>
                <i:EventTrigger EventName="Checked">
                   <i:InvokeCommandAction 
                       Command="{Binding StartWatchingForFolder_Renaimer_Command}"/>
                </i:EventTrigger>
                <i:EventTrigger EventName="Unchecked">
                   <i:InvokeCommandAction 
                       Command="{Binding StopWatchingForFolder_Renaimer_Command}"/>
                   </i:EventTrigger>
                </i:Interaction.Triggers>
         </CheckBox>
      </StackPanel>
</GroupBox>

Все изменения будут отображаться в логах.

При добавлении новых файлов в папку они будут автоматически переименовываться по заданному правилу.

Вторая вкладка выполнена в аналогичном стиле.

Есть два TextBox для ввода начального индекса и количества удаляемых символов. Также есть возможность выбора порядка удаления, с начала или с конца имени файла.

Код представлен ниже.

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>

<!--Путь к файлам и настройка переименования-->
    <GroupBox Header="Настройки" Margin="5" Padding="2">
       <StackPanel>
           <Label Content="Путь к файлам:"/>
           <Grid>
              <Grid.ColumnDefinitions>
                 <ColumnDefinition/>
                 <ColumnDefinition Width="30"/>
              </Grid.ColumnDefinitions>
              <TextBox Grid.Column="0" Name="PathToFolderDeleteString_tb"
                      Text="{Binding PathToFilesForDeleteString_Renamer,
                      Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
              <Button Grid.Column="1" Name="BrowseFolderDeleteString_btn" Content="..." 
                  Click="BrowseFolderDeleteString_btn_OnClick"/>
            </Grid>
            <Label Content="Порядок удаления:"/>
            <StackPanel Orientation="Horizontal">
                <RadioButton GroupName="turn" Content="Начало=>Конец" Margin="5" IsChecked="{Binding BeginningOrEnd}" />
                <RadioButton GroupName="turn" Content="Конец=>Начало" Margin="5"/>
            </StackPanel>
            <Label Content="Начать с:"/>
            <TextBox Name="StartPoint_tb" Text="{Binding StartPointForDelete_Renaimer}"/>
            <Label Content="Сколько удалять:"/>
            <TextBox Name="NumCharForDelete_tb" Text="{Binding NumOfCharForDelete_Renaimer}"/>
       </StackPanel>
    </GroupBox>

<!--Запуск переименования-->
<GroupBox Header="Запуск переименовывания" Grid.Column="1" Margin="5" Padding="5">
     <StackPanel Margin="10">
        <Button Name="RenameFilesDeleteString_btn" Command="{Binding DeleteStringFromFileName_Command}" 
                Content="Переименовать файлы" />
     </StackPanel>
</GroupBox>
</Grid>

На этом этапе заканчивается процесс создания визуальной части приложения. Если есть какие-то вопросы, то пишите в комментарии

Во второй части я расскажу как реализовать класс ViewModel и логику выполнения переименования файлов. Ссылка на исходный код программы будет там же.