小小菜学设计模式之 文件名管理器 ver 1.0

 

 

 

买了本大话设计模式,看的饶有兴致,于是也想来实践一下. 做个什么东西玩玩

想到自己文件(尤其的音乐文件)很多,有时候这些文件的文件名又是没有规范的,

于是想到做一个文件名管理器.

顺便也来练练设计模式.

以循序渐进的方式来吧.

先给出我想实现的第一版的功能需求:

1, 用一个列表框,来加载当前加载到程序中的文件的文件名,

2,添加不同种类的编号, 01,02格式或1,2,3,001,002等格式,添加为前缀或者后缀形式

3,   主面板使用常见编号方式以及更改某一文件属性形式

4音乐文件因为包含很多特殊信息如ID3信息,放在第二版制作用一个选项卡来占位

 

第一版我打算不用任何设计模式,只按目前直觉上的一些过程化设计来做.

 

首先是画界面(小菜一个,WPF也是刚刚接触,基础基本为零哈,见谅见谅)

代码
   
   
< Window x:Class ="文件名管理器_ver1.MainWindow"
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
Title
="文件名管理器 ver 1.0" Height ="376" Width ="701" Icon ="透明head.png" >
< Grid Margin ="3 3 3 3" >
< Label Content ="文件列表:" Margin ="0,0,88,0" Name ="label1" HorizontalAlignment ="Right" Height ="40" VerticalAlignment ="Top" />
< TabControl Name ="tabControl1" Margin ="0,0,147,0" >
< TabItem Header ="普通文件" Name ="tabOrdinaryFile" >
< Grid >
< GroupBox Header ="文件信息" Margin ="6,6,6,69" Name ="groupBox1" >
< GroupBox.ContextMenu >
< ContextMenu >
< MenuItem Header ="aaa" />
< MenuItem Header ="aaa" />
< MenuItem Header ="aaa" />
</ ContextMenu >
</ GroupBox.ContextMenu >
< Grid >
< Label Content ="文件名:" Name ="lstFilename" Height ="24" Width ="60" Margin ="6,20,0,0" HorizontalAlignment ="Left" VerticalAlignment ="Top" />
< Label Content ="大小:" Name ="labSizeTitle" Height ="24" Width ="60" Margin ="6,50,0,0" HorizontalAlignment ="Left" VerticalAlignment ="Top" />
< Label Content ="路径:" Name ="labPathTitle" Height ="24" Width ="60" Margin ="6,80,0,0" HorizontalAlignment ="Left" VerticalAlignment ="Top" />
< Label Content ="属性:" Name ="labAttributeTitle" Height ="24" Width ="60" Margin ="6,110,0,0" HorizontalAlignment ="Left" VerticalAlignment ="Top" />
< TextBox Height ="23" HorizontalAlignment ="Left" Margin ="72,22,0,0" Name ="txtFileName" VerticalAlignment ="Top" Width ="120" />
< CheckBox ToolTip ="编号为2时,编号形式为01,02,以此类推" Content ="启用编号? 位数:" Height ="16" HorizontalAlignment ="Left" Margin ="198,25,0,0" Name ="checkBox1" VerticalAlignment ="Top" Click ="checkBox1_Checked" />
< TextBox IsEnabled ="False" Height ="23" HorizontalAlignment ="Left" Margin ="305,19,0,0" Name ="txtDigit" VerticalAlignment ="Top" Width ="25" Text ="2" />
< RadioButton Content ="编号前缀" ToolTip ="将编号添加为前缀形式,如001.XXX" Height ="16" HorizontalAlignment ="Left" Margin ="346,26,0,0" Name ="rdoPrefix" GroupName ="Method" VerticalAlignment ="Top" IsEnabled ="False" IsChecked ="True" />
< RadioButton Content ="编号后缀" ToolTip ="将编号添加为后缀,如XXX.001" Height ="16" HorizontalAlignment ="Left" Margin ="416,26,0,0" Name ="rdoPostfix" GroupName ="Method" VerticalAlignment ="Top" IsEnabled ="False" />
< Label Content ="--" Height ="28" HorizontalAlignment ="Left" Margin ="72,50,0,0" Name ="labSize" VerticalAlignment ="Top" />
< Label Content ="--" Height ="28" HorizontalAlignment ="Left" Margin ="72,80,0,0" Name ="labPath" VerticalAlignment ="Top" />
< CheckBox Content ="只读" Height ="16" HorizontalAlignment ="Left" Margin ="72,115,0,0" Name ="chkReadonly" VerticalAlignment ="Top" IsEnabled ="False" IsChecked ="False" />
< CheckBox Content ="隐藏" Height ="16" HorizontalAlignment ="Left" Margin ="119,115,0,0" Name ="chkHide" VerticalAlignment ="Top" IsEnabled ="False" IsChecked ="False" />
</ Grid >
</ GroupBox >
< Button Content ="将更改批量修改到文件" HorizontalAlignment ="Left" Margin ="353,0,0,6" Name ="btnBatch" Width ="137" IsEnabled ="False" Height ="30" VerticalAlignment ="Bottom" Click ="btnBatch_Click" />
< Button Content ="保存信息到当前文件" HorizontalAlignment ="Left" Margin ="210,0,0,6" Name ="btnSingle" Width ="137" Height ="30" VerticalAlignment ="Bottom" Click ="btnSingle_Click" />
< Button Content ="打开文件" HorizontalAlignment ="Left" Margin ="12,0,0,6" Name ="btnOpen" Width ="66" Height ="30" VerticalAlignment ="Bottom" Click ="btnOpen_Click" />
< Button Content ="打开文件夹" Height ="30" HorizontalAlignment ="Left" Margin ="84,0,0,6" Name ="button1" VerticalAlignment ="Bottom" Width ="66" Click ="button1_Click" />
</ Grid >
</ TabItem >
< TabItem Header ="音乐文件" Name ="tabMusicFile" >
< Grid />
</ TabItem >
</ TabControl >
< ListBox Name ="lstFilelist" SelectionMode ="Extended" HorizontalAlignment ="Right" Width ="146" Margin ="0,21,0,0" DragOver ="lstFilelist_DragOver" IsEnabled ="True" SelectionChanged ="lstFilelist_SelectionChanged" >
< ListBox.ContextMenu >
< ContextMenu >
< MenuItem Header ="添加文件" />
< MenuItem Header ="添加文件夹" />
< MenuItem Header ="删除选定条目" />
< MenuItem Header ="清空整个列表" />
</ ContextMenu >
</ ListBox.ContextMenu >
</ ListBox >
</ Grid >
</ Window >

 

 

因为基础太差,因此在画界面的时候完全是摸索着来的,没有系统看过任何关于WPF的教程,如果有时间得系统学学WPF哈

界面画出来是这样的:

 小小菜学设计模式之 文件名管理器 ver 1.0_第1张图片

比较丑哈,仅仅为实现功能用.

说说一步步实现的思路吧:

 主要用到的FCL中的数据结构和类

List<FileInfo> 用来存放加载的文件信息

FolderBrowserDialog 用来做文件夹浏览

OpenFileDialog 用来做文件浏览

 

首先是该程序可以加载一个或多个文件到列表框中,

本来想用一个按钮实现打开文件和打开文件夹的功能,

但是发现FCL提供的类库里面没有这样一个东东,

而且即使在具体操作上也很难实现,

比如,你不能确定,当前双击一个文件夹,

究竟是打开该文件夹好,还是加载该文件夹的内容好.

网上搜索了很久也没发现类似的东西,因此就分开做了俩按钮,一个用于打开文件夹,一个用于打开一个或多个文件。

(由于时间关系,目前只做了打开一个或多个文件的功能)

打开一个或多个文件的代码如下:

 

代码
   
   
// 打开文件
private void btnOpen_Click( object sender, RoutedEventArgs e)
{

ofd.Multiselect
= true ;
if (ofd.ShowDialog() == true )
{
for ( int i = 0 ; i < ofd.SafeFileNames.Length; i ++ )
{
// 判断当前列表中是否已经存在该文件信息
if ( ! curAddedFiles.Contains( new FileInfo(ofd.FileNames[i])))
{
curAddedFiles.Add(
new FileInfo(ofd.FileNames[i]));
}
}
/* 最初做数据绑定的时候,
* 思路是用一个Dictionary来存放文件名以及该文件的完整路径,在加载文件时,然后遍历
* 但是发现这样做有很多麻烦的事情会发生,比如我需要在ListBox的SelectionChanged事件类似于
* ((KeyValuePair<string, string>)((sender as ListBox).SelectedItem)).Key
* 这样的转型语句来获取到文件信息,这样做编码量和效率应该都很低
*/

lstFilelist.Items.Refresh();
// 注意,必须要重新创建视图。否则不会在该listbox中显示新的数据源
lstFilelist.ItemsSource = curAddedFiles;
lstFilelist.DisplayMemberPath
= " Name " ; // 以FileInfo类中的Name字段来作为显示的源,但是listbox里面存的是一条条的FileInfo对象

}
}

当在listbox中加载了该文件后,就要实现在每在listbox中选一个条目的时候,左边的详细信息应该予以绑定才行.

这个可以用Listbox的SelectionChanged事件来实现

 

代码
   
   
private void lstFilelist_SelectionChanged( object sender, SelectionChangedEventArgs e)
{
curSelectedFiles
= e.AddedItems as List < FileInfo > ;
curFileInf
= e.AddedItems[ 0 ] as FileInfo;
// *这种方法同样可以实现*/ txtFileName.Text = ((KeyValuePair<string, string>)((sender as ListBox).SelectedItem)).Key;
txtFileName.Text = System.IO.Path.GetFileNameWithoutExtension(curFileInf.FullName); // 此函数可以去掉文件名的扩展名和路径,这样用户更改文件名时也不用考虑扩展名的问题
labPath.Content = curFileInf.DirectoryName;
chkReadonly.IsChecked
= curFileInf.Attributes.HasFlag(FileAttributes.ReadOnly); // HasFlag其实是对FileAttributes的一组位运算,因为文件属性本来就是以位信息来存的
chkHide.IsChecked = curFileInf.Attributes.HasFlag(FileAttributes.Hidden);
labSize.Content
= FormatFileSize(curFileInf.Length); // FormatFileSize是一个格式化文件大小的函数,网上看到的.
}

这样,我们就实现了将文件选入程序,并且查看单个文件的信息的功能

更改单个文件只需要在button事件里 写一句代码:

curFileInf.MoveTo(curFileInf.DirectoryName +"\\"+ txtFileName.Text);

就搞定了

批量更改:

代码
   
   
// 批量更改
private void btnBatch_Click( object sender, RoutedEventArgs e)
{

if ( string .IsNullOrEmpty(txtFileName.Text))
{
MessageBox.Show(
" 请先指定一个文件名 " );
return ;
}
if (MessageBox.Show( " 该功能将以您输入的文件名为标准 为所选定的文件加上您指定的前缀或后缀 " , " 注意! " ,MessageBoxButton.YesNo) == MessageBoxResult.No)
{
return ;
}
string setDigit = "" ;
for ( int i = 0 ; i < int .Parse(txtDigit.Text); i ++ )
{
setDigit
+= " 0 " ;
}
if (rdoPrefix.IsChecked == true )
{
// 以前缀形式添加
for ( int i = 0 ; i < curAddedFiles.Count; i ++ )
{
curAddedFiles[i].MoveTo(curFileInf.DirectoryName
+ " \\ " +
string .Format( " {0: " + setDigit + " } " , i) + txtFileName.Text + curFileInf.Extension);
// ↑ 拼接一段格式化字符串 比如如果你设置的是两位那么拼接的结果就是 ("{0:00"} ", i) 那么文件名也将显示为 01,02,下同
}
}
else if (rdoPostfix.IsChecked == true )
{
// 以后缀形式添加
for ( int i = 0 ; i < curAddedFiles.Count; i ++ )
{
string name = curFileInf.DirectoryName + " \\ " + txtFileName.Text +
string .Format( " {0: " + setDigit + " } " , i) + curFileInf.Extension;
curAddedFiles[i].MoveTo(name);
}
}
}

 

当点击“启用编号”复选框后 “将更改批量修改到文件” “编号位数”“前后缀等” 也设置为可用,

这个只需要checkbox的一个click事件,在里面判断一下就可以解决。很简单 不贴代码了

 

至此,整个程序的初版功能就到此为止,虽然简单,但是也花了我好几个晚上的时间,看来还需大大努力啊.效果如下图

小小菜学设计模式之 文件名管理器 ver 1.0_第2张图片

 

但是这个程序还有非常严重的问题

代码异常 "脏乱差" ,没有任何架构和设计可言,仅仅是简单的实现了我在第一版需求的功能而已(并且还有不少bug ;D),

如果我现在想要增加一些功能

比如:

以不同方式的编号来给文件夹改名,例如 带括弧的编号,

以保留原始文件名的方式给文件加上编号.

另外还有保留的那块音乐文件信息的处理

如果将所有代码都写到主文件里面

这将是一件很恐怖的事情.

 

因此这周我将这个程序用一些简单的设计模式来重构,以便日后来扩展它的功能

 

  

 

 

你可能感兴趣的:(设计模式)