views:

96

answers:

2

I've a very trivial requirement which makes me go nuts. I've a DataGridView in windows forms application. This contains one databound ComboBox Column. I'm using DisplayMember and ValueMember properties of that combobox.

Now my requirement is ComboBox should show the list of DisplayMembers in drop down list but when user selects one item from it, I should display the part of that DisplayMember in the combobox cell visible to the user. For example.

My display member list looks as below:

"Cust1 - Customer 1" "Cust2 - Customer 2" "Cust3 - Customer 3"

and when user selects any one of them from the above list (Say user selected 'Cust2 - Customer 2') then I need to display the value in the combobox column cell as only "Cust2" instead of complete DisplayMember text.

This DisplayMember list is a combination of two fields from the datasource bound to it i.e. First part points to CustomerCode field and second part points Customer name. I need to display only CustomerCode in the ComboBox cell after user selects one item from the drop down list.

How can I do this? Or should I come up with my own control which will have a different AutoCompleteCustomSource and display member value. Even I'm confused with that approach too.

Update: As no one has come up with any solution to my problem. Now I'm starting a bounty for that, also if anyone can suggest me other way to implement the same functionality, it would be great.

I've even tried to come up with my own control and tried to work on simple combobox to display a different value than the selected dropdown list, even that didn't work. Is there any other way to implement this? Any tips and tricks are greatly appreciable.

@Anurag: Here is the code which I've used. Created a datagridview in the design mode. Created one column of type 'DataGridViewComboBoxColumn' that and named it as CustomerColumn.

In the designer file it looks like below:

private System.Windows.Forms.DataGridViewComboBoxColumn CustomerColumn;

This is the entity class which I've used for datasource

 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
 }

In the form load event I'm doing the following:

  CustomerColumn.DataSource = GetCustomers();
  CustomerColumn.DisplayMember = "NameWithCode";
  CustomerColumn.ValueMember = "Id";
+2  A: 

Hi,

I know that this is not perfect solution, but I looked for a better one and I didn't find, so I went to a workaround

I did the following:

  1. when the user open the ComboBox, I change the DisplayMember to "NameWithCode"

  2. when the user close it, I return it to "CustCode"

You can Access to the ComboBox control by DataGridView.EditingControlShowing event for the DataGridView.

The code:

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;
        };
}

Note: You have to start the DisplayMember with "CustCode"

Good luck!

Homam
@Homam: Thanks for the answer. I've already tried this solution. I couldn't go ahead with this solution because changing the display member affects all the cells in that column, which I dont want. It creates confusion even for the end user. So I opted out of that solution. Anyways that is a good solution if user experience is not a problem.
JPReddy
@JPReddy: Sorry, I didn't understand your problem, the changing must affects only the ComboBox control, so it must not affect any other cell in this column or other column, so can you explain more.
Homam
@Homam: I'm sorry for the last comment. I was using the custom datagridview column instead of DataGridViewComboBoxColumn that's why it was behaving as I stated in the above comment. When I replaced it with DataGridViewComboBoxColumn it works fine. Now the issue with this solution is, it works only when user clicks on drop down button, but not when user starts typing in the combobox. In this case autocomplete source only displays CustCode as display member not changed here. I'm trying to figure out how to switch the display member when user starts typing in the combobox. Any idea?
JPReddy
@JPReddy: Yes, there's TextChanged event for ComboBox, but I didn't test it.
Homam
@Homam: I've done this implementation by using a custom control. I've updated my question. Your solution perfectly suits to my question so I'm awarding this bounty to you.
JPReddy
@JPReddy: Thanks, I hope that I could help you, Good luck!
Homam
+2  A: 

I'm answering my own question because I've implemented my own solution to this by using custom control.

This custom control is created by keeping a textbox above combo box in such a way that only drop down button of combobox is visible.

Now I've created a custom column in datagridview deriving the DataGridViewEditingControl from my usercontrol.

I've added a property in Usercontrol which will take drop down list source from the control which is hosting datagridview.

Now in the EditingControlShowing event I'm setting this property as below

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;
  }
}

This drop down list source is used in the usercontrol to set the autocompletesource to the textbox and datasource to the combobox as below: Whenever I set the DropDownDataSource I'm firing an event in the usercontrol which will do the following. This is to ensure that every time EditingControlShowing event occurs for this column in DataGridView, this source is updated for textbox and combobox in usercontrol.

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

  comboBox1.DataSource = DropDownListSource;
}

Now whenever user starts typing in the textbox autocomplete source will display dropdown list with 'NameWithCode' values and if user selects one of them then I'll set it to the Text propery overidden in my usercontrol which will be used for the cell value in the DataGridView. Now based on the Textbox text (which is NameWithCode) I can get the code part and set it to the text property. If user uses combobox dropdown button to select the item then I'll get the combobox selected text and set it in the Textbox which is ultimately used by the cell for getting value.

This way I could achieve the solution I want.

@Homam, solution also works but when I change the ComboBox's DropDownStyle to allow the user to type the value in the combobox it behaves weirdly and not getting up to the mark solution for my requirement. Hence I used this solution.

JPReddy
@JPReddy: +1 Good job, you're right, I didn't consider the DropDownStyle in other DropDownList style, I've also read your new question [about auto complete], I'm waiting starting bounty for it :D. Good luck!
Homam
@Homam: Thanks for the comment. I've already started my own research for the autocomplete and I hope I'll come up with a solution, if I couldn't succeed then I'll start the bounty :)
JPReddy