上上周给自己定的1.1版的任务还没完全完成
留到了1.2版:
需求:
1,支持拖拽功能 (拖拽排序)
2,支持多种形式的编号
3,将音乐媒体文件的文件名识别并写入到ID3中
4,采用设计模式进行重构
1.2 也还没怎么完成,就累积添加到1.3版...(话说我还真是懒啊... - -b)
1,(拖拽排序)
2,支持多种形式的编号 (添加了替换 插入等功能)
3,将音乐媒体文件的文件名识别并写入到ID3中
4,采用设计模式进行重构
目前的进度
1 完成了拖拽加载,但是拖拽排序没搞定,WPF中很多概念不懂啊 学习ing
2 编号方式依然是两种,但是添加了插入和替换文件名
3 完成了MP3文件信息的批量处理,但是没做其他格式
4 小重构了下,也没能用到具体的设计模式.
目前的效果大概是这样:
好了详细说说实现思路
大话设计模式那书看了难免有把设计模式用到软件设计里面的冲动
但可能智商以及联系的确有限吧,也没能套用上具体的什么设计模式,自己定的功能又有各种不同的因素夹杂在里面 ,看来需要继续努力啊
目前大致的设计是这样的:
从抽象文件管理->一般文件管理->音乐文件管理->具体的音乐文件管理 一路继承下来
在一般文件名管理里实现的方法也很方便的重用到音乐文件管理里面去了
几个类目前的代码如下:
抽象基类
// 抽象的文件管理类
abstract class FileNameManager
{
#region 字段和属性
/* 把它们俩作为成员变量的好处是在整个窗口运行期间,
* 都会保存该选定的文件和添加的文件的状态,如果是局部变量我就要不停的获取状态 */
private List < FileInfo > curAddedFiles; // 当前添加的文件
private List < FileInfo > curSelectedFiles; // 当前选定的文件
public List < FileInfo > CurAddedFiles
{
get { return curAddedFiles; }
set { curAddedFiles = value; }
}
public List < FileInfo > CurSelectedFiles
{
get { return curSelectedFiles; }
set { curSelectedFiles = value; }
}
private FileInfo curFileInf;
/// <summary>
/// 当前文件
/// </summary>
public FileInfo CurFileInf
{
get { return curFileInf; }
set { curFileInf = value; }
}
#endregion
/* 抽象出一个文件名管理基类
*因为作为一个文件名管理器,
*其基本功能是添加文件到该文件名管理器中(不管是添加多个或者单个,或者接受的是文件夹)
*以及更改文件名和替换文件名等功能
* */
/// <summary>
/// 添加文件到当前列表中 可以添加文件名,文件夹名数组
/// </summary>
/// <param name="files"> 文件名数组 </param>
public abstract void AddFiles( string [] files);
/// <summary>
/// 统一更改当前文件名(并编号)
/// </summary>
/// <param name="filename"> 文件名 </param>
/// <param name="changingMethod"> 可选:更改方式(前缀/后缀) </param>
/// <param name="digits"> 可选:位数 </param>
public abstract void ChangeNames( string filename, string changingMethod = null , int digits = - 1 );
/// <summary>
/// 替换当前选定文件名中的字符串
/// </summary>
/// <param name="srcName"> 源字符串 </param>
/// <param name="destName"> 目标字符串 </param>
public abstract void ReplaceName( string srcName, string dstName);
/// <summary>
/// 批量替换文件名中的某串字符
/// </summary>
/// <param name="srcName"> 源字符串 </param>
/// <param name="destName"> 目标字符串 </param>
public abstract void ReplaceNames( string srcName, string dstName);
/// <summary>
/// 在文件名指定位置插入字符串
/// </summary>
/// <param name="Location"> 位置 </param>
/// <param name="insertString"> 字符串 </param>
public abstract void InsertNames( int Location, string insertString, bool IsBackwards);
/// <summary>
/// 在多个文件名指定位置插入字符串
/// </summary>
/// <param name="Location"> 位置 </param>
/// <param name="insertString"> 字符串 </param>
public abstract void InsertName( int Location, string insertString, bool IsBackwards);
}
普通的文件管理类


class OrdinaryFileNameManager : FileNameManager
{
/// <summary>
/// 初始化文件名管理类
/// </summary>
/// <param name="curAddedFiles"> 当前添加的文件 </param>
/// <param name="curFileInf"> 当前选择文件 </param>
public OrdinaryFileNameManager(List < FileInfo > curAddedFiles, FileInfo curFileInf)
{
this .CurAddedFiles = curAddedFiles;
this .CurFileInf = curFileInf;
}
#region 添加文件
/// <summary>
/// 添加文件( 此方法为基本方法,接受统一的外部参数,即文件名的字符串数组 因此设计为public的虚函数)
/// </summary>
/// <param name="files"></param>
public override void AddFiles( string [] files)
{
// 首先判断files数组中的文件夹以及文件名
foreach ( string item in files)
{
if (item.IsDirectory())
{
// 如果是文件夹则调用文件夹方法添加文件
this .AddFileByDirectoryInfo(item);
}
else
{
this .AddFileByFileInfo(item);
}
}
}
/// <summary>
/// 添加文件(按文件信息对象 对外部不公开 仅仅对派生类公开)
/// </summary>
/// <param name="files"></param>
protected virtual void AddFileByFileInfo( string filePath)
{
FileInfo tmpFileInfo = new FileInfo(filePath);
var a = from item in CurAddedFiles
select item.FullName;
// 判断当前列表中是否已经存在该文件信息
if ( ! a.Contains(tmpFileInfo.FullName))
{
CurAddedFiles.Add(tmpFileInfo);
}
}
/// <summary>
/// 添加文件(按目录对象 对外部不公开 仅仅对派生类公开)
/// </summary>
/// <param name="files"> 目录对象数组 </param>
protected virtual void AddFileByDirectoryInfo( string directory)
{
DirectoryInfo tmpDir = new DirectoryInfo(directory);
FileInfo[] tmpFileInfos = tmpDir.GetFiles();
var a = from item in CurAddedFiles
select item.FullName;
foreach (var item in tmpFileInfos)
{
if ( ! a.Contains(item.FullName))
{
CurAddedFiles.Add(item);
}
}
}
#endregion
#region 更改文件名
/// <summary>
/// 统一更改文件名(并编号)
/// </summary>
/// <param name="filename"> 文件名 </param>
/// <param name="changingMethod"> 可选:更改方式(前缀/后缀) </param>
/// <param name="digits"> 可选:位数 </param>
public override void ChangeNames( string filename, string changingMethod = null , int digits = - 1 )
{
if (changingMethod == null || digits == - 1 )
{
// 仅仅更改当前文件
CurFileInf.MoveTo(CurFileInf.DirectoryName + " \\ " + filename + CurFileInf.Extension);
return ;
}
if (CurAddedFiles == null || CurAddedFiles.Count == 0 )
{
throw new Exception( " 还没有添加任何文件! " );
}
string setDigit = "" ;
for ( int i = 0 ; i < digits; i ++ )
{
setDigit += " 0 " ;
}
switch (changingMethod)
{
// 以前缀形式添加
case " Prefix " :
for ( int i = 0 ; i < CurAddedFiles.Count; i ++ )
{
CurAddedFiles[i].MoveTo(CurAddedFiles[i].DirectoryName + " \\ " +
string .Format( " {0: " + setDigit + " } " , i) + filename + CurAddedFiles[i].Extension);
// ↑ 拼接一段格式化字符串 比如如果你设置的是两位那么拼接的结果就是 ("{0:00"} ", i) 那么文件名也将显示为 01,02,下同
}
break ;
// 以后缀形式添加
case " Postfix " :
for ( int i = 0 ; i < CurAddedFiles.Count; i ++ )
{
string name = CurAddedFiles[i].DirectoryName + " \\ " + filename +
string .Format( " {0: " + setDigit + " } " , i) + CurAddedFiles[i].Extension;
CurAddedFiles[i].MoveTo(name);
}
break ;
default :
break ;
}
}
#endregion
#region 替换文件名
/// <summary>
/// 替换当前文件名中的某串字符
/// </summary>
/// <param name="srcName"> 要替换的源字符串 </param>
/// <param name="dstName"> 目的字符串 </param>
public override void ReplaceName( string srcName, string dstName)
{
string newName = CurFileInf.FullName.Replace(srcName, dstName);
CurFileInf.MoveTo(newName);
}
/// <summary>
/// 批量替换文件名中的某串字符
/// </summary>
/// <param name="srcName"> 要替换的源字符串 </param>
/// <param name="dstName"> 目的字符串 </param>
public override void ReplaceNames( string srcName, string dstName)
{
foreach (var item in CurAddedFiles)
{
string newName = item.FullName.Replace(srcName, dstName);
item.MoveTo(newName);
}
}
#endregion
#region 插入文件名
public override void InsertName( int Location, string insertString, bool IsBackwards)
{
if (Location > MinOfFilenameLength())
{
throw new ArgumentOutOfRangeException( " 有文件名长度小于所指示位置! " );
}
if (IsBackwards)
{
string newName = CurFileInf.Name.Insert(CurFileInf.Name.Length - Location + 1 , insertString);
CurFileInf.MoveTo(CurFileInf.DirectoryName + ' \\ ' + newName);
}
else
{
string newName = CurFileInf.Name.Insert(Location, insertString);
CurFileInf.MoveTo(CurFileInf.DirectoryName + ' \\ ' + newName);
}
}
public override void InsertNames( int Location, string insertString, bool IsBackwards)
{
if (Location > MinOfFilenameLength())
{
throw new ArgumentOutOfRangeException( " 有文件名长度小于所指示位置! " );
}
if (IsBackwards)
{
foreach (var item in CurAddedFiles)
{
string newName = item.Name.Insert(item.Name.Length - Location + 1 , insertString);
item.MoveTo(item.DirectoryName + ' \\ ' + newName);
}
}
else
{
foreach (var item in CurAddedFiles)
{
string newName = item.Name.Insert(Location, insertString);
item.MoveTo(item.DirectoryName + ' \\ ' + newName);
}
}
}
#endregion
// 在当前文件中查询文件名长度的最小值(接触不深,小用linq一下^_^)
private int MinOfFilenameLength()
{
var min = (from fileinfo in CurAddedFiles
select fileinfo.Name.Length).Min();
return min;
}
}
音乐文件管理类


abstract class MusicFileNameManager : OrdinaryFileNameManager // 音乐文件管理类
{
/// <summary>
/// 当前音乐文件
/// </summary>
public abstract MusicFile CurMusicInf
{
get ;
set ;
}
/// <summary>
/// 初始化音乐文件名管理类
/// </summary>
/// <param name="curAddedFiles"> 当前添加的文件 </param>
/// <param name="curFileInf"> 当前选择文件 </param>
public MusicFileNameManager(List < FileInfo > curAddedFiles, FileInfo curFileInf)
: base (curAddedFiles, curFileInf)
{
}
/// <summary>
/// 更改当前加载文件的艺术家
/// </summary>
public abstract void ChangeArtists( string name);
/// <summary>
/// 更改当前加载文件的专辑
/// </summary>
public abstract void ChangeAlbums( string name);
}
具体的音乐文件管理类


class Mp3FilenameManager : MusicFileNameManager
{
private Mp3File curMusicInf;
public override MusicFile CurMusicInf
{
get
{
return curMusicInf;
}
set
{
curMusicInf = value as Mp3File;
}
}
public Mp3FilenameManager(List < FileInfo > curAddedFiles, FileInfo curFileInf)
: base (curAddedFiles, curFileInf)
{
}
public override void ChangeAlbums( string name)
{
foreach (var item in CurAddedFiles)
{
if (item.IsMp3File())
{
Mp3File tmp = new Mp3File(item);
tmp.Album = name;
}
}
}
public override void ChangeArtists( string name)
{
foreach (var item in CurAddedFiles)
{
if (item.IsMp3File())
{
Mp3File tmp = new Mp3File(item);
tmp.Artist = name;
}
}
}
}
另一条继承链:


class MusicFile
{
#region 字段及属性
/// <summary>
/// 基本信息
/// </summary>
protected FileInfo basicFileInfo;
/// <summary>
/// 标题
/// </summary>
protected string title = string .Empty;
/// <summary>
/// 艺术家,演唱者
/// </summary>
protected string artist = string .Empty;
/// <summary>
/// 所属专辑
/// </summary>
protected string album = string .Empty;
#endregion
}


/// 该类封装了mp3文件的数据及操作
/// </summary>
class Mp3File : MusicFile
{
FileStream fs;
// mp3文件的标识数据
byte [] tagBody = new byte [ 128 ];
public FileInfo BasicFileInfo
{
get { return base .basicFileInfo; }
set { base .basicFileInfo = value; }
}
public string Artist
{
get
{
// WPF中的控件不能正确识别'\0',因此要将其去掉
return Encoding.Default.GetString(tagBody, 33 , 30 ).TrimEnd( ' \0 ' );
}
set
{
for ( int i = 0 ; i < Encoding.Default.GetBytes(value).Length; i ++ )
{
tagBody[i + 33 ] = Encoding.Default.GetBytes(value)[i];
}
WriteID3Info();
}
}
public string Title
{
get
{
return Encoding.Default.GetString(tagBody, 3 , 30 ).TrimEnd( ' \0 ' );
}
set
{
for ( int i = 0 ; i < Encoding.Default.GetBytes(value).Length; i ++ )
{
tagBody[i + 3 ] = Encoding.Default.GetBytes(value)[i];
}
WriteID3Info();
}
}
public string Album
{
get
{
return Encoding.Default.GetString(tagBody, 63 , 30 ).TrimEnd( ' \0 ' );
}
set
{
for ( int i = 0 ; i < Encoding.Default.GetBytes(value).Length; i ++ )
{
tagBody[i + 63 ] = Encoding.Default.GetBytes(value)[i];
}
WriteID3Info();
}
}
public Mp3File(FileInfo file)
{
this .BasicFileInfo = file;
GetID3Info();
}
/// <summary>
/// 获取当前添加的MP3音乐文件的相关信息
/// </summary>
public void GetID3Info()
{
string tagFlag;
// 读取MP3文件的最后128个字节的内容
using (fs = new FileStream(BasicFileInfo.FullName, FileMode.Open, FileAccess.Read))
{
fs.Seek( - 128 , SeekOrigin.End);
fs.Read(tagBody, 0 , 128 );
fs.Close();
}
// 取TAG段的前三个字节
tagFlag = Encoding.Default.GetString(tagBody, 0 , 3 );
// 如果没有TAG信息,则直接返回
if ( ! " TAG " .Equals(tagFlag, StringComparison.InvariantCultureIgnoreCase))
{
throw new InvalidDataException( " 指定的MP3文件没有TAG信息! " );
}
}
public void WriteID3Info()
{
using (fs = new FileStream(BasicFileInfo.FullName, FileMode.Open, FileAccess.Write))
{
fs.Seek( - 128 , SeekOrigin.End);
fs.Write(tagBody, 0 , 128 );
fs.Close();
}
}
}
最后是客户端代码:


{
System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog();
OpenFileDialog ofd = new OpenFileDialog();
MusicFileNameManager fnm;
public MainWindow()
{
InitializeComponent();
fnm = new Mp3FilenameManager( new List < FileInfo > (), null );
}
#region 界面逻辑
// 正数插入还是倒数插入
private void checkBox1_Checked_1( object sender, RoutedEventArgs e)
{
label11.Content = " 在文件名中倒数第 " ;
}
private void checkBox1_Unchecked_1( object sender, RoutedEventArgs e)
{
label11.Content = " 在文件名中正数第 " ;
}
// 控制按键输入只能是数字
private void txtDigit_KeyDown( object sender, KeyEventArgs e)
{
TextBox txt = sender as TextBox;
// 屏蔽非法按键
if ((e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9) /* || e.Key == Key.Decimal */ )
{
if (txt.Text.Contains( " . " ) && e.Key == Key.Decimal)
{
e.Handled = true ;
return ;
}
e.Handled = false ;
}
else if (((e.Key >= Key.D0 && e.Key <= Key.D9) /* || e.Key == Key.OemPeriod) && e.KeyboardDevice.Modifiers != ModifierKeys.Shift */ ))
{
if (txt.Text.Contains( " . " ) && e.Key == Key.OemPeriod)
{
e.Handled = true ;
return ;
}
e.Handled = false ;
}
else
{
e.Handled = true ;
}
}
// 激活批量更改相应选项
private void checkBox1_Checked( object sender, RoutedEventArgs e)
{
chkBatchForId.IsChecked = true ;
chkBatchForReplacement.IsChecked = true ;
chkBatchForInsertion.IsChecked = true ;
txtDigit.IsEnabled = true ;
rdoPostfix.IsEnabled = true ;
rdoPrefix.IsEnabled = true ;
btnBatch.IsEnabled = true ;
}
private void checkBox1_Unchecked( object sender, RoutedEventArgs e)
{
chkBatchForId.IsChecked = false ;
chkBatchForReplacement.IsChecked = false ;
txtDigit.IsEnabled = false ;
rdoPostfix.IsEnabled = false ;
rdoPrefix.IsEnabled = false ;
btnBatch.IsEnabled = false ;
chkBatchForInsertion.IsChecked = false ;
}
#endregion
#region 主要功能
// 打开文件
private void btnOpen_Click( object sender, RoutedEventArgs e)
{
ofd.Multiselect = true ;
if (ofd.ShowDialog() == true )
{
fnm.AddFiles(ofd.FileNames);
RefreshList();
}
}
// 打开文件夹
private void button1_Click( object sender, RoutedEventArgs e)
{
if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
fnm.AddFiles( new string [] { fbd.SelectedPath });
}
RefreshList();
}
// 列表选定项更改时
private void lstFilelist_SelectionChanged( object sender, SelectionChangedEventArgs e)
{
if (e == null )
{
return ;
}
if (e.AddedItems.Count != 0 )
{
List < FileInfo > tmp = new List < FileInfo > ();
foreach (var item in lstFilelist.SelectedItems)
{
tmp.Add(item as FileInfo);
}
fnm.CurSelectedFiles = tmp;
fnm.CurFileInf = lstFilelist.SelectedItem as FileInfo;
// *这种方法同样可以实现*/ txtFileName.Text = ((KeyValuePair<string, string>)((sender as ListBox).SelectedItem)).Key;
txtFileName.Text = System.IO.Path.GetFileNameWithoutExtension(fnm.CurFileInf.FullName); // 此函数可以去掉文件名的扩展名和路径,这样用户更改文件名时也不用考虑扩展名的问题
labPath.Content = fnm.CurFileInf.DirectoryName;
chkReadonly.IsChecked = fnm.CurFileInf.Attributes.HasFlag(FileAttributes.ReadOnly); // HasFlag其实是对FileAttributes的一组位运算,因为文件属性本来就是以位信息来存的
chkHide.IsChecked = fnm.CurFileInf.Attributes.HasFlag(FileAttributes.Hidden);
labSize.Content = FileInfoHelper.FormatFileSize(fnm.CurFileInf.Length); // FormatFileSize是一个格式化文件大小的函数,网上看到的
if (tabMusicFile.IsSelected)
{
if (fnm.CurFileInf.IsMp3File())
{
txtAlbum.IsEnabled = true ;
txtArtist.IsEnabled = true ;
txtTitle.IsEnabled = true ;
fnm.CurMusicInf = new Mp3File(lstFilelist.SelectedItem as FileInfo);
txtMp3Filename.Text = System.IO.Path.GetFileNameWithoutExtension(fnm.CurFileInf.FullName);
txtAlbum.Text = (fnm.CurMusicInf as Mp3File).Album;
txtArtist.Text = (fnm.CurMusicInf as Mp3File).Artist;
txtTitle.Text = (fnm.CurMusicInf as Mp3File).Title;
}
else
{
txtAlbum.Clear();
txtArtist.Clear();
txtTitle.Clear();
txtMp3Filename.Text = " 该文件不是MP3文件 " ;
txtAlbum.IsEnabled = false ;
txtArtist.IsEnabled = false ;
txtTitle.IsEnabled = false ;
}
}
}
else
{
txtFileName.Text = "" ;
labPath.Content = "" ;
chkReadonly.IsChecked = false ;
chkHide.IsChecked = false ;
labSize.Content = "" ;
}
}
// 更改一个文件
private void btnSingle_Click( object sender, RoutedEventArgs e)
{
if (fnm.CurFileInf == null )
{
MessageBox.Show( " 您还没有选定一个文件!请先选择! " );
return ;
}
if (tabOrdinaryFile.IsSelected)
{
fnm.ChangeNames(txtFileName.Text);
RefreshList();
return ;
}
if (tabReplacement.IsSelected)
{
if ( string .IsNullOrEmpty(txtReplaceSrc.Text))
{
MessageBox.Show( " 源字符串不能为空! " );
return ;
}
fnm.ReplaceName(txtReplaceSrc.Text, txtReplaceDest.Text);
RefreshList();
}
if (tabInsert.IsSelected)
{
if ( string .IsNullOrEmpty(txtLocation.Text) || string .IsNullOrEmpty(txtInsertContent.Text))
{
MessageBox.Show( " 插入位置或插入内容不能为空! " );
return ;
}
fnm.InsertName( int .Parse(txtLocation.Text), txtInsertContent.Text, ( bool )chkIsBackwards.IsChecked);
RefreshList();
}
}
// 批量更改
private void btnBatch_Click( object sender, RoutedEventArgs e)
{
if (fnm.CurAddedFiles.Count == 0 )
{
MessageBox.Show( " 您还没有选定任何文件!请先选择! " );
return ;
}
if (tabOrdinaryFile.IsSelected)
{
if ( string .IsNullOrEmpty(txtFileName.Text))
{
MessageBox.Show( " 请先指定一个文件名 " );
return ;
}
if (MessageBox.Show( " 该功能将以您输入的文件名为标准 为所选定的文件加上您指定的前缀或后缀\n是否继续? " , " 注意! " , MessageBoxButton.YesNo) == MessageBoxResult.No)
{
return ;
}
fnm.ChangeNames(txtFileName.Text, ( bool )rdoPrefix.IsChecked ? " Prefix " : " Postfix " ,
Convert.ToInt32(txtDigit.Text));
RefreshList();
return ;
}
if (tabReplacement.IsSelected)
{
if ( string .IsNullOrEmpty(txtReplaceSrc.Text))
{
MessageBox.Show( " 源字符串不能为空! " );
return ;
}
fnm.ReplaceNames(txtReplaceSrc.Text, txtReplaceDest.Text);
RefreshList();
}
if (tabInsert.IsSelected)
{
if ( string .IsNullOrEmpty(txtLocation.Text) || string .IsNullOrEmpty(txtInsertContent.Text))
{
MessageBox.Show( " 插入位置或插入内容不能为空! " );
return ;
}
fnm.InsertNames( int .Parse(txtLocation.Text), txtInsertContent.Text, ( bool )chkIsBackwards.IsChecked);
RefreshList();
}
}
// 拖放文件到窗口
private void lstFilelist_Drop( object sender, DragEventArgs e)
{
string [] files = e.Data.GetData(DataFormats.FileDrop, false ) as string [];
if (files != null )
{
fnm.AddFiles(files);
RefreshList();
}
}
// 上下文菜单-删除
private void MenuItem_Click_Delete( object sender, RoutedEventArgs e)
{
foreach (var item in fnm.CurSelectedFiles)
{
fnm.CurAddedFiles.Remove(item);
}
RefreshList();
}
// 上下文菜单-清空
private void MenuItem_Click_Clear( object sender, RoutedEventArgs e)
{
fnm.CurAddedFiles.Clear();
RefreshList();
}
// 刷新列表框
protected void RefreshList()
{
lstFilelist.Items.Refresh(); // 注意,必须要重新创建视图。否则不会在该listbox中显示新的数据源
lstFilelist.ItemsSource = fnm.CurAddedFiles;
lstFilelist.DisplayMemberPath = " Name " ;
}
#endregion
#region 音乐文件管理
private void btnSaveArtist_Click( object sender, RoutedEventArgs e)
{
(fnm.CurMusicInf as Mp3File).Artist = txtArtist.Text;
}
private void btnSaveAlbum_Click( object sender, RoutedEventArgs e)
{
(fnm.CurMusicInf as Mp3File).Album = txtAlbum.Text;
}
private void btnSaveTitle_Click( object sender, RoutedEventArgs e)
{
(fnm.CurMusicInf as Mp3File).Title = txtTitle.Text;
}
private void btnBatchChangeArtist_Click( object sender, RoutedEventArgs e)
{
if (MessageBox.Show( " 当前操作将更改已加载的所有MP3文件的艺术家!\n确定吗? " , " 警告 " ,MessageBoxButton.OKCancel) == MessageBoxResult.Cancel)
{
return ;
}
fnm.ChangeArtists(txtArtist.Text);
}
private void btnBatchChangeAlbum_Click( object sender, RoutedEventArgs e)
{
if (MessageBox.Show( " 当前操作将更改已加载的所有MP3文件的专辑名!\n确定吗? " , " 警告 " , MessageBoxButton.OKCancel) == MessageBoxResult.Cancel)
{
return ;
}
fnm.ChangeAlbums(txtAlbum.Text);
}
private void tabControl_SelectionChanged( object sender, SelectionChangedEventArgs e)
{
if (tabMusicFile.IsSelected)
{
btnBatch.IsEnabled = false ;
lstFilelist_SelectionChanged( this , null );
}
else
{
if (chkBatchForId.IsChecked == true )
{
btnBatch.IsEnabled = true ;
}
}
}
#endregion
}
整个项目目前大概就是这个样子了,还没有做wma的部分,
整体设计看起来是没什么问题的,
音乐文件与具体的音乐文件是泛化关系
,抽象的音乐文件管理类操作抽象的音乐文件,
但是其实目前是有严重问题的,在客户端访问时,并不能做到彻底屏蔽具体的实现,
我还是必须在客户端知道一个文件是否是MP3文件,而不能做到MP3文件和WMA文件同一性的处理
因为在抽象的音乐管理类中访问的是抽象的音乐文件类,所以在操作具体的文件时还得转型,否则就无法访问具体MP3类里的字段或属性(考虑过重写属性,但是貌似这样让整个结构看起来更乱了)
而且,如果我现在加入了wma类的处理,那么整个客户端还得改,还得判断一个文件的类型,(考虑过让音乐文件继承FileInfo类,如果可以继承的话,处理起来就比较简单,因为基类设计的是处理FileInfo,but..FileInfo不可以继承 = =b)
现在我感觉整个项目都有点乱了,加之WPF刚开始学,数据绑定还用的是最基本的办法,所以1.x版本到此结束,开始着手2.x版~全部重做好了~~阿门...