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

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

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

顺便也来练练设计模式.

以循序渐进的方式来吧.

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

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哈

界面画出来是这样的:

 

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

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

 主要用到的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事件,在里面判断一下就可以解决。很简单 不贴代码了

 

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

 

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

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

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

比如:

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

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

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

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

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

 

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

 

  

 

 

 posted on 2010-10-24 17:41  filod  阅读(456)  评论(0编辑  收藏  举报