对于.NET winforms datagridview,我希望组合框列对每行都有一组不同的值

时间:2011-01-27 20:44:36

标签: .net visual-studio winforms visual-studio-2010 datagridview

我有一个DataGridView,我绑定到POCO。我有数据绑定工作正常。但是,我添加了一个组合框列,我希望每行都有所不同。具体来说,我有一个购买物品网格,其中一些有尺寸(如成人XL,成人L)和其他项目不规模(如汽车磁铁。)

基本上我想要改变的是数据网格中组合框列的DATA SOURCE。可以这样做吗?

我可以将哪些事件挂钩,以便我可以更改每行的某些列的属性?可接受的替代方法是在用户单击或标记到行中时更改属性。这是什么事?

赛斯

修改
我需要更多关于这个问题的帮助。随着Triduses帮助我很接近,但我需要更多的信息。

首先,根据问题,CellFormatting事件确实是更改组合框列的DataSource的最佳/唯一事件。我问,因为我正在做一些相当资源/数据密集的事情,而不仅仅是格式化单元格。

其次,只需将鼠标悬停在单元格上即可调用cellformatting事件。我尝试在 if-block 中设置FormattingApplied属性,然后在 if-test 中检查它,但是返回了一个奇怪的错误消息。我理想的情况是,我会为每一行应用更改组合框的数据源一次,然后用它完成。

最后,为了设置组合框colunm的数据源,我必须能够将if块内的Cell转换为DataGridViewComboBoxColumn类型,以便我可以用行填充它或设置数据源或其他东西。这是我现在的代码。

Private Sub ProductsDataGrid_CellFormatting(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles ProductsDataGrid.CellFormatting

    If e.ColumnIndex = ProductsDataGrid.Columns("SizeDGColumn").Index Then ' AndAlso Not e.FormattingApplied Then
        Dim product As LeagueOrderProductInfo = DirectCast(ProductsDataGrid.Rows(e.RowIndex).DataBoundItem, LeagueOrderProductInfo)
        Dim sizes As LeagueOrderProductSizeList = product.ProductSizes
        sizes.RemoveSizeFromList(_parentOrderDetail.SizeID)

        'WHAT DO I DO HERE TO FILL THE COMBOBOX COLUMN WITH THE sizes collection.

    End If

End Sub

请帮忙。我完全陷入困境,这个任务项目应该花费一个小时,现在我已经超过了4个小时。顺便说一句,我也愿意通过采取一个完全不同的方向来解决这个问题(只要我可以快速完成。)

赛斯

5 个答案:

答案 0 :(得分:3)

不幸的是,没有一个。您将要使用的是CellFormatting event

这将触发每个单元格,但你可以通过检查单元格的列索引来确定你是否在正确的列中,然后如果你在列中你想要工作就可以做你的逻辑用。

如果您决定在选择行而不是显示行时更改它,则可以改为使用RowEnter。

以下是如何使用此事件的代码示例。这个将列设置为包含图像。

 Private Sub dgActiveOccurrences_CellFormatting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles dgActiveOccurrences.CellFormatting
        If e.ColumnIndex = dgActiveOccurrences.Columns("colActiveUnreadFlag").Index Then
            Dim occ As Occurrence = DirectCast(dgActiveOccurrences.Rows(e.RowIndex).DataBoundItem, Occurrence)
            If occ.LastReadBy <> OccurrenceSession.Self.UserManager.MyStaffRecord.StaffId Then
                e.Value = My.Resources.Icon_UnreadFlag
            End If
        End If
End Sub

答案 1 :(得分:2)

我没有采用捕捉事件的方式来改变每行的组合框中的显示值...看看这种方法(示例),它非常简单易用,并且完全符合您的要求IMHO:

  1. 使用两个简单属性(名称,类型)声明一个Item类

  2. 创建一个包含两列的DataGridView(一个用于Name,第二个用于Type,其中ColumnType = DataGridViewComboBoxColumn和dataPropertyName = Type)

  3. 将“我的假设”poco's列表“附加”到DataGridView

  4. 然后只通过你的行集合循环一次; 抓取该行的DataGridViewComboBoxColumn ; 根据您对该行中poco的标准更改其项目属性。

  5. 我把它留给你抓住特定行的poco,或者从行中的硬编码列中读取一些属性......

    以下是一些示例代码:

    namespace DataGridViewCustomComboboxItemsPerRow
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
    
                List<int> types = new List<int>();
                List<Item> items = new List<Item>();
                Item item;
                for (int i = 0; i < 100; i++)
                {
                    item = new Item();
                    item.Name = "Item" + i.ToString();
                    item.Type = i;
    
                    items.Add(item);
                    types.Add(i);
                }
    
                //typeDataGridViewComboBoxColumn.DataSource = types;
                itemBindingSource.DataSource = items;
            }
    
            private void Form1_Shown(object sender, EventArgs e)
            {
                DataGridViewComboBoxCell dgvc;
    
                for (int i = 0; i < dataGridView1.Rows.Count; i++)
                {
                    dgvc = (DataGridViewComboBoxCell)dataGridView1.Rows[i].Cells[1];
    
                    // Your CUSTOM code here, I just did some stupid thing here...
                    dgvc.Items.Add(i - 1);
                    dgvc.Items.Add(i);
                    dgvc.Items.Add(i + 1);
                }
            }
        }
    
        public class Item
        {
            private string _name;
            private int _type;
    
            public string Name
            {
                get { return _name; }
                set { _name = value; }
            }
    
            public int Type
            {
                get { return _type; }
                set { _type = value; }
            }
        }
    }
    

    代码在C#中,但非常基本,所以我想它不会在VB.NET中引起问题。而且这段代码实际上是一次性循环(O(n))来为不同的行配置你的组合而不是完成它。

    希望这会有所帮助。的Joep。

答案 2 :(得分:0)

我不确定这对你是否可行。 您可以在dataGridView1_DataBindingComplete事件

中尝试相同的操作吗?
foreach (DataGridViewRow var in dataGridView1.Rows)
{
      if (var.Cells[0] is DataGridViewComboBoxCell)
      {
          (var.Cells[0] as DataGridViewComboBoxCell).Items.Add("first col values");
      }
      if (var.Cells[1] is DataGridViewComboBoxCell)
      {
          (var.Cells[1] as DataGridViewComboBoxCell).Items.Add("second col values");
      }
}

答案 3 :(得分:0)

如果无法向此网格添加行,则可以使用事件DataBindingComplete,当网格完成数据绑定时会触发此事件,如果可以添加行,则必须使用此事件NewRowNeeded此事件如果单击网格底部的新行,则会触发 你不会担心多次填充相同的组合

答案 4 :(得分:0)

您可以使用CellBeginEdit事件执行此操作。处理事件,检查正在编辑的列是否是DataGridViewComboBox列并更改组合框中的项目。

如果将数据源绑定到组合框,则可能无效。我只是尝试手动添加项目列表:

void grid_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
    if (grid.Columns[e.ColumnIndex].Name == "MyComboColumn")
    {
        // get the value of a different cell in this row that will be used to determine which values are in the combobox
        string other_value = grid[0, e.RowIndex].Value.ToString();

        // get the combobox cell being edited
        DataGridViewComboBoxCell cell = (DataGridViewComboBoxCell)grid[e.ColumnIndex, e.RowIndex];

        // update the list of items in the combobox
        cell.Items.Clear();
        if (other_value == "something")
            cell.Items.AddRange(new object[] { "Value1", "Value2" });
        else
            cell.Items.AddRange(new object[] { "Value3", "Value4" });

    }
}

注意:此代码未经测试,我现在不在我的开发机器上。