C#文件列表

C#文件列表

窗体页面制作

需要控件Panel,设置属性Dock控制所处的位置。用于在窗体上分组和组织其他控件。

Pannel里拖入Lable,Button,TextBox,Listview,FolderBrowerDialog,ContexMenuStrip,ImageList等控件。

ListView:可以平铺的布局,用于以多种视图模式(如大图标、小图标、列表、详细信息等)显示数据项列表。

FolderBrowerDialog:文件夹浏览对话框,用于让用户选择一个文件夹。

ContexMenuStrip:上下文菜单条,用于为其他控件提供右键上下文菜单。

ImageList:用于存储一组图像,这些图像可以被其他控件(如ListView,TreeView等)共享和使用。

留白的方式:

  • 第一种方式:可以用anchor,拉伸。

  • 第二种方法:padding边框到子控件之间的距离。

    ​ margin边框到上一级控件的距离。

拖控件的顺序:占满剩余空间的那个,选择最后拖进去的布局控件,这样就不会占用别的布局控件的空间了。想修改顺序的时候,就去修改designer文件里的代码。

嵌套层级比较多的时候,可以选中当前的,然后点击esc键,就可以返回上一级嵌套。

转到定义,designer文件里有详细的设置。designer设计的代码,设置的比较早。在Form里面设置,会比较晚,也可以写在窗体加载函数里。

拖一个控件,它会在designer文件里实例化。可以自己写个类实例一个控件,不用写在designer里面。

字体Font会被继承,字体颜色也可以被继承,背景颜色,会被下一级沿用。

构造函数


public Form1()
{
    // 初始化组件,VS帮开发者生成界面布局,开发者向设计器拖放的所有控件都在在FormXXX.Designer.cs文件生成代码。
    // InitializeComponent()就是在FormXXX.Designer.cs文件中。
    InitializeComponent();

    // 手动创建控件
    /*Button button = new Button();
    button.Size = new System.Drawing.Size(180, 54);
    button.Name = "btnByCode";
    button.Text = "通过代码创建的按钮";
    // button位置
    //button.Location = new Point(50, 60);
    panel1.Controls.Add(button);*/

    // 手动绑定事件
    // 完整写法:
    //大图标ToolStripMenuItem.Click += new EventHandler(SearchToolStripMenuItem_Click);

    // 简写:只要方法能满足委托(方法的形参和返回值,与委托保持一致)。
    // 事件不能连等。
    /*大图标ToolStripMenuItem.Click += SearchToolStripMenuItem_Click;
    小图标ToolStripMenuItem.Click += SearchToolStripMenuItem_Click;
    列表ToolStripMenuItem.Click += SearchToolStripMenuItem_Click;
    详细信息ToolStripMenuItem.Click += SearchToolStripMenuItem_Click;*/

    // 循环绑定事件
    var list = 查看ToolStripMenuItem.DropDownItems;
    foreach (var item in list)
    {
        ToolStripMenuItem tsmi = item as ToolStripMenuItem;
        tsmi.Click += SearchToolStripMenuItem_Click;
    }

    var list2 = 排列方式ToolStripMenuItem.DropDownItems;
    foreach (var item in list2)
    {
        if (item is ToolStripSeparator) continue;
        ToolStripMenuItem tsmi = item as ToolStripMenuItem;
        tsmi.Click += ArrangeModeToolStripMenuItem_Click;
    }
}

窗体加载


private void Form1_Load(object sender, EventArgs e)
 {
     this.Text = "文件列表";
     // 窗体加载时,默认加载D盘
     LoadFolder(@"D:\");
 }
 

右键菜单-查看


// sender发送者,事件的发送者,你点击了哪个控件,sender就是谁。sender装箱
private void SearchToolStripMenuItem_Click(object sender, EventArgs e)
{
    // 1.选中
    // 让当前点击的菜单项选中
    ToolStripMenuItem tsmi = sender as ToolStripMenuItem;
    tsmi.Checked = true;

    // 其他的菜单项不选中
    var list = 查看ToolStripMenuItem.DropDownItems;
    foreach (var item in list)
    {
        ToolStripMenuItem oneItem = item as ToolStripMenuItem;
        if (oneItem.Name == tsmi.Name) continue;  // 把当前点击的菜单项跳过。
        oneItem.Checked = false;
    }
    // 2。功能(设置查看模式)
    listView1.View = (View)Enum.Parse(typeof(View), tsmi.Name);
    /*if (tsmi.Text == "大图标")
    {
        listView1.View = View.LargeIcon;
    }
    else if (tsmi.Text == "小图标")
    {
        listView1.View = View.SmallIcon;
    }
    else if (tsmi.Text == "列表")
    {
        listView1.View = View.List;
    }
    else if (tsmi.Text == "详细信息")
    {
        listView1.View = View.Details;
    }
    else if (tsmi.Text == "平铺")
    {
        listView1.View = View.Tile;
    }*/
}

右键菜单-排列方式


private void ArrangeModeToolStripMenuItem_Click(object sender, EventArgs e)
{
    // 1.选中
    // 当前点击的项
    ToolStripMenuItem tsmi = sender as ToolStripMenuItem;
    tsmi.Checked = true;
    
    // 分两组,每一组互斥选中
    var list = 排列方式ToolStripMenuItem.DropDownItems;
    // 循环取每一组中选中的项
    ToolStripMenuItem item1 = null;  // 保存排列方式
    ToolStripMenuItem item2 = null;  // 保存升序或降序

    foreach (var item in list)
    {
        // A.实现选中
        if (item is ToolStripSeparator) continue;  // 中线
        ToolStripMenuItem oneItem = item as ToolStripMenuItem;
        // tsmi.Tag.ToString()=="1"判断是点击属于哪一组。
        // oneItem.Tag.ToString() == "1"判断循环当中的某项属于哪一组。
        if (oneItem.Tag.ToString() == "1" && tsmi.Tag.ToString() == "1")
        {
            if (oneItem.Text != tsmi.Text) oneItem.Checked = false;
        }
        else if (oneItem.Tag.ToString() == "2" && tsmi.Tag.ToString() == "2")
        {
            if (oneItem.Text != tsmi.Text) oneItem.Checked = false;
        }

        // B.实现把每一组选中的项记录下来
        if (oneItem.Tag.ToString() == "1")
        {
            if (!oneItem.Checked) continue;
            item1 = oneItem;
        }
        else if (oneItem.Tag.ToString() == "2")
        {
            if (!oneItem.Checked) continue;
            item2 = oneItem;
        }
    }

    // 2.功能(排列方式,排序)
    /*
     ToolStripMenuItem item1 = null;  // 保存排列方式
     ToolStripMenuItem item2 = null;  // 保存升序或降序
     foreach (var item in list)
     {
         if (item is ToolStripSeparator) continue;  // 中线
         ToolStripMenuItem oneItem = item as ToolStripMenuItem;
         if (oneItem.Tag.ToString() == "1")
         {
             if (!oneItem.Checked) continue;
             item1 = oneItem;
         }
         else if (oneItem.Tag.ToString() == "2")
         {
             if (!oneItem.Checked) continue;
             item2 = oneItem;
         }
     }*/

    // 排序,比较:IComparer,有两组比较的条件 
    // 参数1:按XX比较。参数2:升序或降序
    // ListViewItemSorter属性给Sort()设置比较器。
    listView1.ListViewItemSorter = new MyListItemSorter(item1.Text, item2.Checked);
    listView1.Sort();
}

点击按钮切换目录

 
 private void btnOpen_Click(object sender, EventArgs e)
  {
      FolderBrowserDialog dialog = new FolderBrowserDialog();
      dialog.ShowNewFolderButton = false;
      //dialog.Description = "fjdlsjfldsjfljdsf";
      //dialog.RootFolder=Environment.SpecialFolder.Windows;
      DialogResult dialogResult = dialog.ShowDialog();
      if (dialogResult == DialogResult.OK)
      {
          txtPath.Text = dialog.SelectedPath;
          LoadFolder(txtPath.Text);
      }
  }
  

加载目录方法


// 加载选择的目录下的文件夹及文件(一层)
private void LoadFolder(string path)
{
    // 1.先清空原来的列表
    listView1.Items.Clear();

    // 2.加载文件夹
    // 拿到目录实例
    DirectoryInfo directoryInfo = new DirectoryInfo(path);
    // 拿到目录下的所有的子文夹
    DirectoryInfo[] subDirs = directoryInfo.GetDirectories();
    for (int i = 0; i < subDirs.Length; i++)
    {
        DirectoryInfo dir = subDirs[i];

        Console.WriteLine(dir.Attributes);
        if ((dir.Attributes & FileAttributes.Hidden) > 0) continue;  // 排除隐藏文件夹
        if ((dir.Attributes & FileAttributes.System) > 0) continue;  // 排除系统文件夹

        /*string[] arr = dir.Attributes.ToString().Split(new string[] {", "},StringSplitOptions.None);
        if (Array.IndexOf(arr, "Hidden") != -1) continue;
        if (Array.IndexOf(arr, "System") != -1) continue;*/

        // ListViewItem可以又包含子项, ListViewItem能不能填写图片
        // ImageIndex图片索引,是ListView1控件关联的ImageList中的图片的序号
        ListViewItem listViewItem = new ListViewItem(dir.Name, "shell32_1_4.ico");
        //ListViewItem listViewItem = new ListViewItem(dir.Name, 0);

        listViewItem.SubItems.Add(dir.LastWriteTime.ToString("yyyy/MM/dd HH:mm"));
        listViewItem.SubItems.Add("文件夹");
        listViewItem.SubItems.Add("");

        // 先把列表中添加的项用ListItem实体保存下来,目的:将来排序用。
        ListItem model = new ListItem()
        {
            Name = dir.Name,
            UpdateTime = dir.LastWriteTime,
            Type = "文件夹",
            Size = 0M
        };
        listViewItem.Tag = model;  

        // 给listView1添加一项,项的类型ListViewItem
        listView1.Items.Add(listViewItem);
    }

    // 3.加载文件
    // 拿到目录下的所有的文件
    FileInfo[] files = directoryInfo.GetFiles();
    Array.ForEach(files, file =>
    {
        ListViewItem listViewItem = new ListViewItem(file.Name, 1);
        listViewItem.SubItems.Add(file.LastWriteTime.ToString("yyyy/MM/dd HH:mm"));
        listViewItem.SubItems.Add(GetType(file.Extension));
        listViewItem.SubItems.Add(Math.Ceiling(file.Length / 1024M).ToString("N0") + " KB");

        // 先把列表中添加的项用ListItem实体保存下来,目的:将来排序用。
        ListItem model = new ListItem()
        {
            Name = file.Name,
            UpdateTime = file.LastWriteTime,
            Type = GetType(file.Extension),
            Size = Math.Ceiling(file.Length / 1024M)
        };
        listViewItem.Tag = model;

        listView1.Items.Add(listViewItem);
    });

}

// 根据文件扩展名,得到文件类型
private string GetType(string extension)
{
    if (extension == ".txt")
    {
        return "文本文档";
    }
    else if (extension == ".bat")
    {
        return "Windows 批处理文件";
    }
    // ......其他文件类型自行判断
    else
    {
        return "未知";
    }
}

LIstItem.cs


namespace FileList.Model
{
    public class ListItem
    {
        public string Name { get; set; }
        public DateTime UpdateTime { get; set; }
        public string Type { get; set; }
        public decimal Size { get; set; }
    }
}

Compare.cs


namespace FileList.Compare
{
    public class MyListItemSorter : IComparer
    {
        // 保存排序的列
        private string colName = string.Empty;
        // 保存升序或降序
        private bool asc = false; 

        public  MyListItemSorter(string colName, bool asc) { 
            this.colName = colName;
            this.asc = asc;
        }

        // x排序前一项,y排序后一项
        public int Compare(object x, object y)
        {
            ListViewItem item1 = (ListViewItem)x;
            ListViewItem item2 = (ListViewItem)y;

            ListItem model1 = (ListItem)item1.Tag;
            ListItem model2 = (ListItem)item2.Tag;

            if (colName == "名称")
            {
                // 按字符串比较
               return CompareString(model1.Name, model2.Name, asc);
            }
            else if (colName == "修改日期") {
                return CompareString(model1.UpdateTime.ToString("yyyy-MM-dd HH:mm:ss"), model2.UpdateTime.ToString("yyyy-MM-dd HH:mm:ss"), asc);
            }
            else if (colName == "类型")
            {
                return CompareString(model1.Type, model2.Type, asc);
            }
            else if (colName == "大小")
            {
                return CompareDecimal(model1.Size, model2.Size, asc);
            }
            return 0;
        }

        private int CompareString(string name1, string name2, bool asc)
        {
            if (asc)
                return name1.ToLower().CompareTo(name2.ToLower());
            else
                return name2.ToLower().CompareTo(name1.ToLower());
        }

        private int CompareDecimal(decimal size1, decimal size2, bool asc)
        {
            if (asc)
                return (int)(size1 - size2);
            else
                return (int)(size2 - size1);
        }
    }
}

在windows平台上,图片不合适,造成和应用程序分辨率不匹配造成的失真问题,模糊,可以通过放开应用程序配置清单app.manifest里的一个注释来解决这个问题。


<application xmlns="urn:schemas-microsoft-com:asm.v3">
  <windowsSettings>
    <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
  </windowsSettings>
</application>

如何添加app.mainfest?

  • 方法一:在项目上右键单击,选择属性。在默认打开的选项卡中选择嵌入带默认设置的清单。没有效果。

  • 方法二:在项目上右键单击,添加项,选择应用程序配置清单文件(仅限Windows),就可以了。

posted @ 2024-08-17 15:49  海域  阅读(53)  评论(0编辑  收藏  举报