Click here to Skip to main content
15,886,362 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Can anyone help me with the code below. I want to make a MultiColumn listbox.
I have adapt my standard code but this give me one Collom with data in my listbox with data (IDMateriaal).

How do I customize the code below to get the data in different collems.


ListBoxMateriaal
|| IDMateriaal | Omschrijving | Omschrijving2 ||

private void MateriaalBOX()
        {
            using (connection = new SqlConnection(connectionstring))

            using (SqlDataAdapter adapter = new SqlDataAdapter("select [IDMateriaal],Omschrijving, Omschrijving2 from Materiaal ORDER BY Omschrijving ASC", connection))
                try
                {
                    DataTable materiaallijst = new DataTable();
                    adapter.Fill(materiaallijst);
                    //
                    ListBoxMateriaal.HorizontalScrollbar = true;
                    ListBoxMateriaal.FormattingEnabled = true;
                    ListBoxMateriaal.MultiColumn = true;
                    ListBoxMateriaal.ScrollAlwaysVisible = true;
                   ListBoxMateriaal.TabIndex = 0;
                    //
                    //ListBoxMateriaal.DisplayMember = "Omschrijving";
                    ListBoxMateriaal.ValueMember = "IDMateriaal";
                    ListBoxMateriaal.Items.AddRange(new object[]
                    {
                      "IDMateriaal, IDMateriaal",
                      "Omschrijving, Omschrijving",
                      "Omschrijving2, Omschrijving2",

                        });

                    ListBoxMateriaal.DataSource = materiaallijst;
                }


What I have tried:

https://msdn.microsoft.com/en-us/library/system.windows.forms.listbox.multicolumn(v=vs.110).aspx
Posted
Updated 12-Apr-16 1:24am
Comments
Suvabrata Roy 12-Apr-16 7:13am    
Did you face any error?
MaikelO1 12-Apr-16 7:20am    
No error, but there is only one collum
Suvabrata Roy 12-Apr-16 7:22am    
How many rows you have as result?

1 solution

For a ListBox Multicolumn = true just pushes the (single column of) data into another column instead of using a scrollbar.

Instead of using a ListBox use a ListView e.g.
C#
private void MateriaalBOX()
        {
            ListBoxMateriaal.TabIndex = 0;
            ListBoxMateriaal.Items.Clear();
            ListBoxMateriaal.View = View.Details;

            ListBoxMateriaal.Columns.Add("IDMateriaal");
            ListBoxMateriaal.Columns.Add("Omschrijving");
            ListBoxMateriaal.Columns.Add("Omschrijving2");

            using (var connection = new SqlConnection(connectionstring))
            {
                var query = "select [IDMateriaal],Omschrijving, Omschrijving2 from Materiaal ORDER BY Omschrijving ASC";
                using (var adapter = new SqlDataAdapter(query, connection))
                {
                    try
                    {
                        DataTable materiaallijst = new DataTable();
                        adapter.Fill(materiaallijst);

                        for (int i = 0; i < materiaallijst.Rows.Count; i++)
                        {
                            DataRow dr = materiaallijst.Rows[i];
                            ListViewItem listitem = new ListViewItem(dr["IDMateriaal"].ToString());
                            listitem.SubItems.Add(dr["Omschrijving"].ToString());
                            listitem.SubItems.Add(dr["Omschrijving2"].ToString());
                            ListBoxMateriaal.Items.Add(listitem);
                        } 
..etc                    

Alternatively you could use a DataGridView to display the data.
The only other alternative I can think of would be to write a custom control.

[EDIT - response to OP's comment is easier here than in comments]
Quote:
want to use the IDMateriaal field as SelectedValue, because in my final solution, I don't need the ID field be visualized.. Is this possible?

Yes. I suggest the following changes to the code I offered above:
C#
//ListBoxMateriaal.Columns.Add("IDMateriaal");   //Don't need a column for the ID
ListBoxMateriaal.Columns.Add("Omschrijving");
ListBoxMateriaal.Columns.Add("Omschrijving2");
ListBoxMateriaal.MultiSelect = false;           //Only select one row
ListBoxMateriaal.FullRowSelect = true;          //Select the whole row, not just column 1

using (var connection = new SqlConnection(connectionstring))
{
    var query = "select [IDMateriaal],Omschrijving, Omschrijving2 from Materiaal ORDER BY Omschrijving ASC";
    using (var adapter = new SqlDataAdapter(query, connection))
    {
        try
        {
            DataTable materiaallijst = new DataTable();
            adapter.Fill(materiaallijst);

            for (int i = 0; i < materiaallijst.Rows.Count; i++)
            {
                DataRow dr = materiaallijst.Rows[i];
                ListViewItem listitem = new ListViewItem(dr["Omschrijving"].ToString());    //Note item in now based on this column
                listitem.SubItems.Add(dr["Omschrijving2"].ToString());

                listitem.Tag = dr["IDMateriaal"];                   // Store the ID for later on
                ListBoxMateriaal.Items.Add(listitem);
            }
And you can get to the id of the selected row like this
C#
private void ListBoxMateriaal_SelectedIndexChanged(object sender, EventArgs e)
{
    lblSelected.Text = (ListBoxMateriaal.SelectedItems.Count > 0) ? ListBoxMateriaal.SelectedItems[0].Tag.ToString() : "Nothing Selected";
}



[EDIT - changes after OP comments]
C#
private void MateriaalBOX()
{
    ListBoxMateriaal.TabIndex = 0;
    ListBoxMateriaal.Items.Clear();
    ListBoxMateriaal.View = View.Details;

    ListBoxMateriaal.Columns.Add("Materiaalgroep");
    ListBoxMateriaal.Columns.Add("Omschrijving");
    ListBoxMateriaal.Columns.Add("Omschrijving2");
    ListBoxMateriaal.Columns.Add("Datum_wijziging");

    ListBoxMateriaal.MultiSelect = false;
    ListBoxMateriaal.FullRowSelect = true;

    using (var connection = new SqlConnection(connectionstring))
    {
        var query = "SELECT [IDMateriaal], Omschrijving, Omschrijving2, Datum_wijziging FROM Materiaal WHERE Omschrijving like (@Omschrijving) order by Omschrijving ASC";

        using (var adapter = new SqlDataAdapter(query, connection))
        {
            SqlParameter parm = adapter.SelectCommand.Parameters.AddWithValue("@Omschrijving", "%" + TX_Materiaalstuk_Zoeken.Text + "%");
            try
            {
                DataTable materiaallijst = new DataTable();
                adapter.Fill(materiaallijst);

                for (int i = 0; i < materiaallijst.Rows.Count; i++)
                {
                    DataRow dr = materiaallijst.Rows[i];
                    ListViewItem listitem = new ListViewItem(dr["IDMateriaal"].ToString());
                    listitem.SubItems.Add(dr["Omschrijving"].ToString());
                    listitem.SubItems.Add(dr["Omschrijving2"].ToString());
                    listitem.SubItems.Add(dr["Datum_wijziging"].ToString());


                    listitem.Tag = dr["IDMateriaal"]; // Store the ID for later on
                    ListBoxMateriaal.Items.Add(listitem);

                    ListBoxMateriaal.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
                    ListBoxMateriaal.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
                Console.WriteLine(ex.Message);
            }

        }
    }
    ListBoxMateriaal.Columns[3].Width = 0;
}
        private void ListBoxMateriaal_SelectedIndexChanged(object sender, EventArgs e)
        {
            lblSelected.Text = (ListBoxMateriaal.SelectedItems.Count > 0) ? ListBoxMateriaal.SelectedItems[0].Tag.ToString() : "";
            LB_WijzigingingsDatum.Text = (ListBoxMateriaal.SelectedItems.Count > 0) ? ListBoxMateriaal.SelectedItems[0].SubItems[3].Text : "";
 
        }
 
Share this answer
 
v3
Comments
MaikelO1 12-Apr-16 7:56am    
Thanks! This proposal works! Only have another two questions about this solution?

I want to use the IDMateriaal field as SelectedValue, because in my final solution, I don't need the ID field be visualized.. Is this possible?
CHill60 12-Apr-16 8:08am    
Yes it is possible - I've updated my solution with some suggested changes to make this work
MaikelO1 13-Apr-16 4:58am    
I have another question to retrieve data from the table that are not visualized in the list view. I make no column for the field “Datum_wijziging” Because I want to make it visible in a label.

I wrote the following command ; “ LB_WijzigingingsDatum.Text = ListBoxMateriaal.SelectedItems[0].Text; // HELP “ When I make the first selection I still get the wrong information, but I receive data in the label, when i change the selection I get an error..

private void MateriaalBOX()
{
ListBoxMateriaal.TabIndex = 0;
ListBoxMateriaal.Items.Clear();
ListBoxMateriaal.View = View.Details;

ListBoxMateriaal.Columns.Add("Materiaalgroep");
ListBoxMateriaal.Columns.Add("Omschrijving");
ListBoxMateriaal.Columns.Add("Eenheid");
ListBoxMateriaal.Columns.Add("Verkoopprijs");

ListBoxMateriaal.MultiSelect = false;
ListBoxMateriaal.FullRowSelect = true;

using (var connection = new SqlConnection(connectionstring))
{

var query = "SELECT [IDMateriaal], Omschrijving, Inkoop, Opslag, FK_eenheid, Bepaald_Tarief, FK_Materiaalgroep, FK_leverancier,Datum_wijziging, Eenheid, MateriaalGroep, CASE WHEN (Bepaald_Tarief IS NULL) THEN((Inkoop / 100) * Opslag) + Inkoop ELSE Bepaald_tarief END as Verkoop from Materiaal LEFT OUTER JOIN Eenheid ON Materiaal.FK_Eenheid = Eenheid.IDEenheid LEFT OUTER JOIN MateriaalGroep ON Materiaal.FK_Materiaalgroep = MateriaalGroep.IDMateriaalgroep ORDER BY MateriaalGroep DESC, Omschrijving ASC";

using (var adapter = new SqlDataAdapter(query, connection))
{
try
{
DataTable materiaallijst = new DataTable();
adapter.Fill(materiaallijst);

for (int i = 0; i < materiaallijst.Rows.Count; i++)
{
DataRow dr = materiaallijst.Rows[i];
ListViewItem listitem = new ListViewItem(dr["MateriaalGroep"].ToString());
listitem.SubItems.Add(dr["Omschrijving"].ToString());
listitem.SubItems.Add(dr["Eenheid"].ToString());
listitem.SubItems.Add(dr["Verkoop"].ToString());
listitem.SubItems.Add(dr["Datum_wijziging"].ToString());

listitem.Tag = dr["IDMateriaal"]; // Store the ID for later on
ListBoxMateriaal.Items.Add(listitem);

ListBoxMateriaal.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
ListBoxMateriaal.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
}
}


private void ListBoxMateriaal_SelectedIndexChanged(object sender, EventArgs e)
{
XX_Selected.Text = (ListBoxMateriaal.SelectedItems.Count > 0) ? ListBoxMateriaal.SelectedItems[0].Tag.ToString() : "";

LB_WijzigingingsDatum.Text = ListBoxMateriaal.SelectedItems[0].Text; // HELP
}
CHill60 13-Apr-16 5:58am    
You need to be look at SelectedItems[0].SubItems[n].Text (where n is the column for that data).
If you want data in the ListView that is not visible you can set the column width to 0 after it has been populated (i.e. after the loop)
I'm also getting an error when I try to select a different line - can't look at it right now but I will try to come back to it before I leave today
CHill60 13-Apr-16 7:08am    
I came back to this and realised I'd missed what should have been obvious to me :(
The SelectedIndexChanged is called more times than you realise - it is called when the control is first being displayed - but there will be nothing selected. It is also called as you "unselect" the previous item - again nothing will be selected. So the solution to the error is to check there are any selected items before attempting to use them e.g.
LB_WijzigingingsDatum.Text = (ListBoxMateriaal.SelectedItems.Count > 0) ? ListBoxMateriaal.SelectedItems[0].SubItems[3].Text : "";
Note you will have to change the '3' I've used to n from my previous comment - i.e. the column number (base 0) in which this data is hidden

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900