winforms 如何使DataGrid控件中的按钮打开同一行上的文件路径?

jqjz2hbq  于 2023-01-17  发布在  其他
关注(0)|答案(2)|浏览(112)

我在一个项目管理系统上工作,我在每个Datagrid行中都有一个按钮。当单击按钮时,应该打开您拥有该特定行的"路径"列的文件。我应该如何做到这一点。有没有一种方法可以使每一行都成为一个控件或其他东西?

代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System;
using System.Diagnostics;

namespace Blender_Project_manager
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Maindata.Rows.Add(addname.Text, addpath.Text);
        }

        private void Maindata_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            
        }
    }
}

我试过

private void Maindata_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    System.Diagnostics.Process.Start(path.ToString());
}

但最后却给了我一个错误,"系统找不到指定的文件"

cu6pst1q

cu6pst1q1#

您的帖子有几个相关问题:

  • 如何避免错误The system cannot find the file specified
  • 有没有办法让每一行都成为一个控件之类的?
  • 如何在DataGrid控件中制作按钮
  • 如何使按钮打开同一行上的文件路径

可能有一个简单的解决方案可以避免该异常。请尝试使用以下语法打开文件:

System.Diagnostics.Process.Start("explorer.exe", path);

由于很难说问题究竟出在哪里,我也会对你的问题提供一个全面的回答。


扑克牌图片来源:Boardgame pack v2(知识共享许可证),作者:肯尼Vleugels。

查找文件

如果这些文件是安装的一部分(在编译时已知),则可以通过设置“复制到输出目录”属性并将其引用为

path =
    Path.Combine(
        AppDomain.CurrentDomain.BaseDirectory,
        "Images",
        "boardgamePack_v2",
        "PNG",
        "Cards",
        "shortFileName.png" // Example filename
    );

另一方面,如果用户可以修改它们,则它们属于

path =        
    Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
        "AppName", // Example app name
        "Images",
        "boardgamePack_v2",
        "PNG",
        "Cards",
        "shortFileName.png" // Example filename
    ));

定义行行为

为了 “使每一行成为[...]某物”,需要一个具有与DataGridView中的列对应的公共属性的类。该类将绑定到DataGridView的DataSource属性,例如,通过创建BindingList<Card>。下面是一个最小的示例:

class Card
{
    public string Name { get; set; }
    public string FilePath { get; set; }
    public Image Image{ get; set; }

    internal static string ImageBaseFolder { get; set; } = string.Empty;
    public string GetFullPath() => Path.Combine(ImageBaseFolder, FilePath);
}

在网格控件中创建按钮

在此示例中,DataGridView控件在加载MainForm的方法中初始化。由于没有与Open列对应的类属性,因此必须在从绑定自动生成列之后添加该属性。添加了一个处理程序,我们可以检查该处理程序以确定是否单击了按钮。

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        Card.ImageBaseFolder = 
            Path.Combine(
                AppDomain.CurrentDomain.BaseDirectory,
                "Images",
                "boardgamePack_v2",
                "PNG",
                "Cards"
            );
    }
    internal BindingList<Card> Cards { get; } = new BindingList<Card>();
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        dataGridViewCards.DataSource = Cards;

        #region F O R M A T    C O L U M N S
        Cards.Add(new Card()); // <- Auto generate columns
        dataGridViewCards.Columns["Name"].AutoSizeMode= DataGridViewAutoSizeColumnMode.Fill;
        dataGridViewCards.Columns["FilePath"].AutoSizeMode= DataGridViewAutoSizeColumnMode.Fill;
        dataGridViewCards.Columns["FilePath"].HeaderText = "File Path";
        DataGridViewImageColumn imageColumn = (DataGridViewImageColumn) dataGridViewCards.Columns["Image"];
        imageColumn.ImageLayout = DataGridViewImageCellLayout.Zoom;
        imageColumn.Width = 100;
        imageColumn.HeaderText = string.Empty;

        // Add the button column (which is not auto-generated).
        dataGridViewCards.Columns.Insert(2, new DataGridViewButtonColumn
        {
            Name = "Open",
            HeaderText = "Open",
        });
        Cards.Clear();
        #endregion F O R M A T    C O L U M N S

        // Add a few cards
        Cards.Add(new Card(Value.Ten, Suit.Diamonds));
        Cards.Add(new Card(Value.Jack, Suit.Clubs));
        Cards.Add(new Card(Value.Queen, Suit.Diamonds));
        Cards.Add(new Card(Value.King, Suit.Clubs));
        Cards.Add(new Card(Value.Ace, Suit.Hearts));

        dataGridViewCards.ClearSelection();

        // Detect click on button or any other cell.
        dataGridViewCards.CellContentClick += onAnyCellContentClick;
    }

使按钮打开同一行上的文件路径

在处理程序中,通过索引从绑定的集合中检索卡片并获得完整路径,如果使用下面的语法,您可能会在Process.Start中获得更好的结果:

private void onAnyCellContentClick(object? sender, DataGridViewCellEventArgs e)
    {
        if (dataGridViewCards.Columns[e.ColumnIndex].Name.Equals("Open"))
        {
            var card = Cards[e.RowIndex];
            var path = card.GetFullPath();
            Process.Start("explorer.exe", path);
        }
    }
}
w8f9ii69

w8f9ii692#

我建议在GridView中添加一个DataGridViewButtonColumn
下面是一个YouTube教程,介绍如何添加和使用此类列:https://www.youtube.com/watch?v=mCxAvQVpCH0
希望能有所帮助。

相关问题