5

I'm trying to set the.DisplayMember property of a ComboBox in C#, but I want to bind it to multiple columns in the .DataSouce.

My SQL looks like this:

SELECT PersNbr, PersFirstName, PersMiddleName, PersLastName
FROM Pers WHERE PersNbr = :persNbr;

I'm saving this query in a DataTable so each column selected has it's own column in the Datatable.

I want to make the .DisplayMember a combination of PersFirstName + PersMiddleName + PersLastName so their full name appears like this:

comboBox.DisplayMemeber = "PersFirstName" + "PersMiddleName" + "PersLastName"

I know I can just to this on the query:

SELECT PersNbr, (PersFirstName || PersMiddleName || PersLastName) PersName

and then just do this:

comboBox.DisplayMember = "PersName";

but I don't want to do the formatting of data in the database layer since it's not supposed to be there.

How else can I achieve this in Winforms?

Jimenemex
  • 3,104
  • 3
  • 24
  • 56
  • Possible duplicate of [DisplayMemberPath concatenation](https://stackoverflow.com/questions/10187375/displaymemberpath-concatenation) – zambonee Aug 26 '18 at 23:21
  • 2
    @zambonee that is XAML. He asks for a windows forms. As much as i know you can't set a combobox item template in windows forms. Maybe there might be an event fired on DataPopulated or something like that. But that should't be the way we follow – DLL_Whisperer Aug 26 '18 at 23:25

3 Answers3

10

You can create an expression column and then use it as a DisplayMember:

dataTable.Columns.Add(
    "FullName", 
    typeof(string), 
    "PersFirstName + ' ' + PersMiddleName + ' ' PersLastName");

comboBox.DisplayMember = "FullName";
hardkoded
  • 18,915
  • 3
  • 52
  • 64
  • 3
    Wow, i didn't know there is something such as Expression Column. That's interesting – DLL_Whisperer Aug 26 '18 at 23:28
  • Is it possible to use a function inside the expression? If `PersMiddleName` is `null` in my DB, an extra space is added. Is there a quick way to solve this, or would I need to evaluate the individual row values. – Jimenemex Aug 27 '18 at 14:10
  • @Jimenemex you have the list of available options in the doc https://learn.microsoft.com/en-us/dotnet/api/system.data.datacolumn.expression?redirectedfrom=MSDN&view=netframework-4.7.2#System_Data_DataColumn_Expression – hardkoded Aug 27 '18 at 14:17
3

Don't use heavy DataTable only for transporting data from database to the code. Create a class, load data in it then you will be able format data with full support of programming language you are using (functions and etc.)

public class Person
{
    public int Number { get; set; }
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }

    public string Name => $"{FirstName} {MiddleName} {LastName}"; 
}

// Load data
var persons = new List<Person>();

using (var connection = new SqlConnection(connectionsString))
using (var command = connection.CreateCommand())
{
    command.CommandText = "SELECT PersNbr, PersFirstName, PersMiddleName, PersLastName FROM Pers";
    connection.Open();

    using (var reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            var person = new Person
            {
                Number = reader.GetInt32(0),
                FirstName = reader.GetString(1),
                MiddleName = reader.GetString(2),
                LastName = reader.GetString(3),
            };
            persons.Add(person);
        }
    }
}

combobox.DisplayMember = "Name";
combobox.DataSource = persons;
Fabio
  • 31,528
  • 4
  • 33
  • 72
1

If you are using a datatable you should do this process on database layer. I've recommend you to do this by using POCO classes. But if you really want to do this on application layer and by using datatable here is the following code:

dataTable.Columns.Add("PersName");
foreach(DataRow item in dataTable.Rows)
{
    item["PersName"] =  item["PersFirstName"] + item["PersMiddleName"] + ["PersLastName"]
}

Then you can set the DisplayMember propert to "PersName".

DLL_Whisperer
  • 815
  • 9
  • 22