【问题标题】:How to show only certain columns in a DataGridView with custom objects如何使用自定义对象仅显示 DataGridView 中的某些列
【发布时间】:2013-02-10 02:16:41
【问题描述】:

我有一个 DataGridView,我需要向它添加自定义对象。考虑以下代码:

DataGridView grid = new DataGridView();
grid.DataSource = objects;

使用此代码,我得到一个 DataGridView 对象,其中所有属性都作为列。就我而言,我不想显示所有这些信息。我只想显示两三列。我知道我可以设置

AutoGenerateColumns = false

但我不知道以后如何进行。 一种选择是隐藏我不感兴趣的所有列,但我认为最好以相反的方式进行。我该怎么做?

【问题讨论】:

    标签: c# datagridview


    【解决方案1】:

    每当我这样做时,我通常都会将grid.DataSource 设为对象上的 LINQ 投影结果。

    所以是这样的:

    grid.DataSource = objects.Select(o => new
        { Column1 = o.SomeValue, Column2 = o.SomeOtherValue }).ToList();
    

    好消息是您可以将AutoGenerateColumns 设置为true,这将根据投影对象的属性生成列。

    编辑:

    这种方法的一个缺点是,通过将所有内容投影到匿名对象中,例如,在需要在点击事件中访问特定对象的情况下,您可能会遇到问题。

    在这种情况下,您最好定义一个显式视图模型并将您的对象投影到其中。例如,

    class MyViewModel
    {
        public int Column1 { get;set; }
        public int Column2 { get;set; }
    }
    
    grid.DataSource = objects.Select(o => new MyViewModel()
        { Column1 = o.SomeValue, Column2 = o.SomeOtherValue }).ToList();
    

    编辑 2:

    MyViewModel 表示您要在DataGridView 中显示的所有列。示例属性当然应该重命名以适合您正在做的事情。一般来说,ViewModel 的目的是充当一种转换器,在模型(在您的情况下是您的对象列表)和视图之间进行调解。

    如果您想保留对底层对象的引用,最好的方法可能是通过构造函数提供它:

    class MyViewModel
    {
        public int Column1 { get;set; }
        public int Column2 { get;set; }
    
        ....
    
        private SomeType _obj;
    
        public MyViewModel(SomeType obj)
        {
            _obj = obj;
        }
    
        public SomeType GetModel()
        {
            return _obj;
        }
    }
    
    grid.DataSource = objects.Select(o => new MyViewModel(o)
        { Column1 = o.SomeValue, Column2 = o.SomeOtherValue }).ToList();
    

    我使用 getter 方法来检索底层模型对象的原因只是为了避免为其生成列。

    【讨论】:

    • @Overflow012 你这是什么意思?
    • 我需要在连续单击时获取我的自定义对象。如果我这样做,我无法得到它。我是对的?
    • @Overflow012 好点,我明白你的意思。是的,如果你想这样做,那么你需要使用我编辑中的方法。
    • 在你的例子中MyViewModel 是什么?
    • 我试图了解objects 在您的代码中最顶部的含义,在任何一个编辑之前。例如,它是DataTable 吗?谢谢。
    【解决方案2】:

    您还可以在适当的情况下对基础对象中的任何属性使用属性 [Browsable(false)]。这当然会抢占该列,使其无法在其他地方浏览,因此您可能会发现这是不可取的。

    【讨论】:

    • 1+ 这个有很好的观点,但有些 OP 无法理解,所以我们需要一些类似的东西 :D
    【解决方案3】:

    您可以将数据绑定与 AutoGenerateColumns = false 一起使用,并像这样使用 DataPropertyName

    grid.Columns["Column_name_1"].DataPropertyName = "public_property_1";
    grid.Columns["Column_name_2"].DataPropertyName = "public_property_2";
    

    这种方式只有绑定的列会显示在 datagridview 中,如果需要,您可以在编辑器中创建列。公共属性可以是对象中的任何公共属性。

    如果您正在从 datagridview 编辑数据,那么您应该在 set 方法中使用 NotifyPropertyChanged。 请看我的问题/答案here,我会一直解释这一点。

    【讨论】:

      【解决方案4】:

      最简单的方法是将“System.ComponentModel.Browsable”属性添加到 DataModel:

      public class TheDataModel 
      {
             [System.ComponentModel.Browsable(false)]
             public virtual int ID { get; protected set; }
             public virtual string FileName { get; set; }
             [System.ComponentModel.Browsable(false)]
             public virtual string ColumnNotShown1 { get; set; }
             [System.ComponentModel.Browsable(false)]
             public virtual string ColumnNotShown2  { get; set; }
      }
      

      【讨论】:

        【解决方案5】:

        你可以这样做。

        要在DataGridView 中仅显示特定的列,首先您需要像这样在DataTable 中获取数据。

        String query="Your query to dispplay columns from the database";
        SqlCommand cmd=new SqlCommand(query,con); //con is your Connection String
        con.Open();
        DataTable dt=new DataTable();
        SqlDataAdapter da=new SqlDataAdapter(cmd);
        da.Fill(dt); //Now this DataTable is having all the columns lets say
        /* Now take another temporary DataTable to display only particular columns*/
        DataTable tempDT=new DataTable();
        tempDT=dt.DefaultView.ToTable(true,"Your column name","your column name");
        //Now bind this to DataGridView
        grid.DataSource=tempDT;
        con.Close();
        

        我知道这是一个相当长的过程。那些去表演的人可能不喜欢这个。 :P

        但我认为它工作正常。

        【讨论】:

          【解决方案6】:

          这是我来自旧项目的代码。它可以为您的情况工作。

          OleDbDataAdapter da = new OleDbDataAdapter("SELECT * FROM uyeler", baglanti);
          
          da.Fill(dbDataSet1, "uyeler");
          
          //Set AutoGenerateColumns False
          dataGridView1.AutoGenerateColumns = false;
          
          //Set Columns Count
          dataGridView1.ColumnCount = 5;
          
          //Add Columns
          dataGridView1.Columns[0].Name = "İsim"; // name
          dataGridView1.Columns[0].HeaderText = "İsim"; // header text
          dataGridView1.Columns[0].DataPropertyName = "ad"; // field name
          
          dataGridView1.Columns[1].HeaderText = "Soyisim";
          dataGridView1.Columns[1].Name = "Soyisim";
          dataGridView1.Columns[1].DataPropertyName = "soyad";
          
          dataGridView1.Columns[2].Name = "Telefon";
          dataGridView1.Columns[2].HeaderText = "Telefon";
          dataGridView1.Columns[2].DataPropertyName = "telefon";
          
          dataGridView1.Columns[3].Name = "Kayıt Tarihi";
          dataGridView1.Columns[3].HeaderText = "Kayıt Tarihi";
          dataGridView1.Columns[3].DataPropertyName = "kayit";
          
          dataGridView1.Columns[4].Name = "Bitiş Tarihi";
          dataGridView1.Columns[4].HeaderText = "Bitiş Tarihi";
          dataGridView1.Columns[4].DataPropertyName = "bitis";
          
          dataGridView1.DataSource = dbDataSet1;
          dataGridView1.DataMember = "uyeler";
          

          【讨论】:

          • dataGridView1.AutoGenerateColumns = false;防止所有列显示在数据绑定上。谢谢!
          • 你的答案是最有用的,因为他们没有输入ColumnCount。未来的程序员在设置 Column.[0].Name/HeaderText/DataPropertyName 时会遇到这种类型的错误,例如 Null 引用异常
          【解决方案7】:
               SqlCommand cmd6 = new SqlCommand("SELECT * FROM tblinv WHERE invno='" + textBox5.Text + "'",cn);
          
                  SqlDataReader sqlReader6 = cmd6.ExecuteReader();
          
                  if (sqlReader6.HasRows)
          
                  {
                      DataTable dt = new DataTable();
          
                      DataTable dt1 = new DataTable();
          
                      dt.Load(sqlReader6);
          
                      dt1 = dt.DefaultView.ToTable(true, "ChallanNo", "ProductName", "UoM", "Price", "Qty","Subtotal");
          
                      dataGridView2.DataSource = dt1;
                  }
          

          【讨论】:

          • 如果你向提问的人解释这个解决方案会很好,这样他不仅可以复制\粘贴它,还可以通过学习以其他方式从中受益
          【解决方案8】:

          为列表创建新模型 ....

                       var today =DateTime.Today;
                      DailyEnteryList = _context.Tbl_AllEntriries.Where(x => 
                          x.CreatedOn.Value.Date == today.Date).
                          Select(x=> new EntirysModel 
                          {
                              EntiryNo=Convert.ToInt64(x.EntiryNo),
                              CustomerName=x.CustomerName,
                              Date=Convert.ToDateTime(x.Date),
                              ModelName=x.ModelName,
                          }).ToList();
          

          我的EntirysModel

           public class EntirysModel
          {
              public long EntiryNo { get; set; }
              public string CustomerName { get; set; }
              public DateTime Date { get; set; }
              public string ModelName { get; set; }
          }
          

          然后在网格中添加列

          [1]

          https://i.stack.imgur.com/3dZAl.png

          这在我的现金中效果最好 谢谢!!!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-09-24
            • 2012-03-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-06-19
            • 2015-06-24
            相关资源
            最近更新 更多