C#檔案列表

海域發表於2024-08-17

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),就可以了。

相關文章