DataGridViewCombBoxColumn单元格值和不同的下拉列表

时间:2010-10-13 07:29:44

标签: c# winforms datagridview drop-down-menu datagridviewcombobox

我有一个非常微不足道的要求让我疯了。我在Windows窗体应用程序中有一个DataGridView。这包含一个数据绑定ComboBox列。我正在使用该组合框的DisplayMember和ValueMember属性。

现在我的要求是ComboBox应该在下拉列表中显示DisplayMembers列表,但是当用户从中选择一个项目时,我应该在用户可见的组合框单元格中显示该DisplayMember的部分。例如。

我的显示成员列表如下所示:

“Cust1 - 客户1” “Cust2 - 客户2” “Cust3 - 客户3”

当用户从上面的列表中选择其中任何一个时(假设用户选择'Cust2 - Customer 2'),我需要将组合框列单元格中的值显示为“Cust2”而不是完整的DisplayMember文本。< / p>

此DisplayMember列表是绑定到它的数据源的两个字段的组合,即第一部分指向CustomerCode字段,第二部分指向客户名称。用户从下拉列表中选择一个项目后,我需要在ComboBox单元格中仅显示CustomerCode。

我该怎么做?或者我应该提出自己的控件,它将具有不同的AutoCompleteCustomSource和显示成员值。即使我也对这种方法感到困惑。

更新:因为没有人能解决我的问题。现在我开始给予赏金,如果有人可以建议我实现相同功能的其他方式,那就太棒了。

我甚至试图想出自己的控件,并尝试使用简单的组合框来显示与所选下拉列表不同的值,即使这样也不起作用。有没有其他方法来实现这个?任何提示和技巧都非常值得注意。

@Anurag:这是我用过的代码。 在设计模式下创建了一个datagridview。创建了一个类型为“DataGridViewComboBoxColumn”的列,并将其命名为CustomerColumn。

在设计器文件中,它如下所示:

private System.Windows.Forms.DataGridViewComboBoxColumn CustomerColumn;

这是我用于数据源的实体类

 public class Customer
 {
    public int Id { get; set; }
    public string CustCode { get; set; }
    public string CustName { get; set; }
    public string NameWithCode { get; set; }// CustCode - CustName format
 }

在表单加载事件中,我正在执行以下操作:

  CustomerColumn.DataSource = GetCustomers();
  CustomerColumn.DisplayMember = "NameWithCode";
  CustomerColumn.ValueMember = "Id";

3 个答案:

答案 0 :(得分:3)

我正在回答我自己的问题,因为我已经使用自定义控件实现了我自己的解决方案。

这个自定义控件是通过将文本框保持在组合框上方来创建的,这样只有组合框的下拉按钮才可见。

现在我在datagridview中创建了一个自定义列,从我的usercontrol派生出DataGridViewEditingControl。

我在Usercontrol中添加了一个属性,它将从托管datagridview的控件中获取下拉列表源。

现在在EditingControlShowing事件中,我正在设置此属性,如下所示

private void dataGridView2_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
  if(dataGridView2.CurrentCell.ColumnIndex.Equals(0) && e.Control is UserControl1)
  {
    var uscontrol = e.Control as UserControl1;
    uscontrol.DropDownListSource = source;
  }
}

此下拉列表源在usercontrol中用于将autocompletesource设置为文本框,将数据源设置为组合框,如下所示: 每当我设置DropDownDataSource时,我都会在usercontrol中触发一个事件,该事件将执行以下操作。这是为了确保每次在DataGridView中为此列发生EditingControlShowing事件时,都会在usercontrol中为textbox和combobox更新此源。

private void DropDownSourceChanged(object sender, EventArgs eventArgs)
{
  textBox1.AutoCompleteCustomSource = DropDownListSource;
  textBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
  textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;

  comboBox1.DataSource = DropDownListSource;
}

现在每当用户开始在文本框中输入时,自动完成源将显示带有“NameWithCode”值的下拉列表,如果用户选择其中一个,那么我将把它设置为我的usercontrol中覆盖的Text propery,它将用于单元格DataGridView中的值。现在基于Textbox文本(NameWithCode),我可以获取代码部分并将其设置为text属性。 如果用户使用组合框下拉按钮选择项目,那么我将获得组合框所选文本,并将其设置在文本框中,最终由单元格用于获取值。

这样我就可以实现我想要的解决方案。

@Homam,解决方案也可以,但是当我更改ComboBox的DropDownStyle以允许用户在组合框中键入值时,它表现得非常奇怪,而且没有达到我的要求的标记解决方案。因此我使用了这个解决方案。

答案 1 :(得分:2)

我知道这不是完美的解决方案,但我找了一个更好的解决方案而且我找不到,所以我去了解决方法

我做了以下事情:

  1. 当用户打开ComboBox时,我将DisplayMember更改为"NameWithCode"

  2. 当用户关闭它时,我将其返回"CustCode"

  3. 您可以通过DataGridView.EditingControlShowing事件访问DataGridView的ComboBox控件。

    代码:

    private void dataGridView1_EditingControlShowing(object sender, 
        DataGridViewEditingControlShowingEventArgs e)
    {
        var comboBox = e.Control as ComboBox;
    
        comboBox.DropDown += (s1, e1) => comboBox.DisplayMember = "NameWithCode";
    
        comboBox.DropDownClosed += (s2, e2) =>
            {
                // save the last selected item to return it after 
                // reassign the Display Member
                var selectedItem = comboBox.SelectedItem; 
    
                comboBox.DisplayMember = "CustCode";
                comboBox.SelectedItem = selectedItem;
            };
    }
    

    注意:您必须使用DisplayMember

    启动"CustCode" 祝你好运!

答案 2 :(得分:0)

每次攻击事件dataGridView1_EditingControlShowing时都会为事件comboBox.DropDown和comboBox.DropDownClosed添加新的处理程序。这导致这些处理程序的数量和它们的重复调用的增加。此代码决定了这个问题。

private void dataGridView1_EditingControlShowing(object sender, 
      DataGridViewEditingControlShowingEventArgs e)
{
  var comboBox = e.Control as ComboBox;

  comboBox.DropDown += comboBox_DropDown;
  comboBox.DropDownClosed += comboBox_DropDownClosed;
}

private void comboBox_DropDown(object sender, System.EventArgs e)
{
  var comboBox = sender as ComboBox;
  if(comboBox != null)
  {
    comboBox.DropDown -= comboBox_DropDown;
    comboBox.DisplayMember = "NameWithCode";        
  }
}

private void comboBox_DropDownClosed(object sender, System.EventArgs e)
{
  var comboBox = sender as ComboBox;
  if(comboBox != null)
  {
    comboBox.DropDownClosed -= comboBox_DropDownClosed;

    var selectedItem = comboBox.SelectedItem; 

    comboBox.DisplayMember = "CustCode";
    comboBox.SelectedItem = selectedItem;        
  }
}