【问题标题】:DataGridViewCombBoxColumn cell value and different dropdown listDataGridViewCombBoxColumn 单元格值和不同的下拉列表
【发布时间】:2011-04-24 17:01:01
【问题描述】:

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

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

我的显示成员列表如下:

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

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

此 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";

【问题讨论】:

  • 为什么不将值成员设置为“Cust1”
  • @The King:但我不希望 value 成员作为下拉列表。
  • gridview 中的组合框!数据源到底是什么...我的意思是,您用来填充网格/组合框的代码是什么?我可能有一个解决方案
  • @Anurag:它是一个datagridview,其中一列的类型是comboboxcolumn。对于这个组合框列,我分配了一个数据源,它是一个简单的客户对象 {Id, CustCode, CustName}。我将通过将数据源分配给组合框来更新问题。

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


【解决方案1】:

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

我做了以下事情:

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

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

您可以通过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" 开头

祝你好运!

【讨论】:

  • @Homam:感谢您的回答。我已经尝试过这个解决方案。我无法继续使用此解决方案,因为更改显示成员会影响该列中的所有单元格,这是我不想要的。即使对于最终用户,它也会造成混乱。所以我选择退出该解决方案。无论如何,如果用户体验不是问题,这是一个很好的解决方案。
  • @JPReddy: 对不起,我没看懂你的问题,更改必须只影响ComboBox控件,所以不能影响本列或其他列中的任何其他单元格,你能解释一下吗.
  • @Homam:我很抱歉最后的评论。我使用的是自定义 datagridview 列而不是 DataGridViewComboBoxColumn,这就是我在上面评论中所说的行为的原因。当我用 DataGridViewComboBoxColumn 替换它时,它工作正常。现在这个解决方案的问题是,它仅在用户单击下拉按钮时有效,但在用户开始在组合框中输入时无效。在这种情况下,自动完成源仅将 CustCode 显示为此处未更改的显示成员。我试图弄清楚当用户开始在组合框中输入时如何切换显示成员。有什么想法吗?
  • @JPReddy:是的,ComboBox 有 TextChanged 事件,但我没有测试。
  • @Homam:我使用自定义控件完成了这个实现。我已经更新了我的问题。您的解决方案非常适合我的问题,所以我将这笔赏金授予您。
【解决方案2】:

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

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

现在我在 datagridview 中创建了一个自定义列,从我的用户控件派生 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;
  }
}

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

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

  comboBox1.DataSource = DropDownListSource;
}

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

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

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

【讨论】:

  • +1 干得好,你说得对,我没有考虑其他 DropDownList 样式中的 DropDownStyle,我还阅读了你的新问题 [关于自动完成],我正在等待开始赏金为它:D。祝你好运!
  • @Homam:感谢您的评论。我已经开始对自动完成进行自己的研究,我希望我能提出一个解决方案,如果我不能成功,那么我将开始赏金:)
【解决方案3】:

每次触发事件 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;        
  }
}

【讨论】:

  • 解释一下这段代码,具体说明你做了什么
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-21
相关资源
最近更新 更多