locked
Populate DGV based on specific Query RRS feed

  • Question

  • Hi,

    I have a single DataGridView and a single bindingsource.

    The bindingsource is assigned as the DataGridView DataSource.

    Depending on the option selected by the end user, the bindingsource is to be populated with specific data.

    So if user selects option 'A', the bindingsource is populated with database data queries with option 'A'.
    If user selects option 'B', the bindingsource is populated with database data queries with option 'B'.
    And so on.

    I want to hide specific columns in the DataGridView - depending on the option selected.

    What is the best way to do this?

    Should I custom create fields as below?

    Thanks!

    DataGridViewTextBoxColumn IDCol = new DataGridViewTextBoxColumn();
    IDCol.Name = "IDCol";
    IDCol.HeaderText = "User ID";
    IDCol.DataPropertyName = "IDCol";
    Wednesday, February 29, 2012 4:07 PM

Answers

  • You have two options:  Let the DGV auto-generate columns (I think it is the default behavior), or create the columns manually yourself.  I'd go with #1 unless the default behavior is not good enough for you for whatever reason.  This behavior is controlled by the property called AutoGenerateColumns.

    Jose R. MCP

    • Marked as answer by Mike Dos Zhang Wednesday, March 7, 2012 11:25 AM
    Wednesday, February 29, 2012 5:46 PM
  • What is the difference in no of columns for option A & B? If you have few columns, you can set the visible property of column as and when required. And instead of adding column at run time, can't you just bind with datasource?

    Amit Govil | Email

    "Weeks of coding can save you hours of planning"

    • Marked as answer by Mike Dos Zhang Wednesday, March 7, 2012 11:25 AM
    Wednesday, February 29, 2012 5:52 PM
  • If your DataSource for both options is a DataTable meaning the BindingSource.DataSource = SomeDataTable then you can set column mappings of the columns not to display in the DataGridView once the DataTable has been populated. So set columns that you do not want to show as Hidden.

    MSDN Reference


    KSG

    • Marked as answer by Mike Dos Zhang Wednesday, March 7, 2012 11:25 AM
    Wednesday, February 29, 2012 11:00 PM
  • The default column names would be same as you have in your datatable or in the bindingsource(basically it would be the column name that you have in your  table in database). check code below to hide column.

    DataGridView1.Columns["ColumnName"].Visible=False;


    Amit Govil | Email

    "Weeks of coding can save you hours of planning"


    Thursday, March 1, 2012 12:14 PM
  • The columns are auto-generated. There are 2-4 columns I want to hide depending on the table binded to.

    How do I specify what columns to hide when the column name is only generated at runtime?

    You have an array perhaps that has column names not to display no matter what or if the logic is dependent on other things you might have a multi-dimensional array etc. The example below shows two hard coded DataTables used as the data source for a BindingSource which in turn becomes the data source of a DataGridView. After the DataTable is populated and used as the source as mentioned we cycle thru an array of column names, if found hide the column. Hope is clear and assist you with making a decision.

    Public Class frmSelectiveColDemo
        ''' <summary>
        ''' Columns not to display
        ''' </summary>
        ''' <remarks></remarks>
        Private NoShowColumns As String() = {"Process", "Column1"}
        WithEvents bsData As New BindingSource
        Private Sub MockedData1()
            Dim dtGrid As New DataTable()
            dtGrid.Columns.AddRange(New DataColumn() _
                { _
                    New DataColumn("Process", GetType(System.Boolean)), _
                    New DataColumn("Identifier", GetType(System.Int32)), _
                    New DataColumn("Column1", GetType(System.String)), _
                    New DataColumn("Part", GetType(System.String)) _
                } _
            )
            dtGrid.Rows.Add(New Object() {False, 1, "A1", "Item A"})
            dtGrid.Rows.Add(New Object() {False, 2, "B1", "Item B"})
            dtGrid.Rows.Add(New Object() {False, 3, "C1", "Item C"})
            bsData.DataSource = dtGrid
        End Sub
        Private Sub MockedData2()
            Dim dtGrid As New DataTable()
            dtGrid.Columns.AddRange(New DataColumn() _
                { _
                    New DataColumn("Identifier", GetType(System.Int32)), _
                    New DataColumn("Column1", GetType(System.String)), _
                    New DataColumn("Column2", GetType(System.String)), _
                    New DataColumn("Item", GetType(System.String)) _
                } _
            )
            dtGrid.Rows.Add(New Object() {1, "Item A", "A1", "A2"})
            dtGrid.Rows.Add(New Object() {2, "Item B", "B1", "B2"})
            dtGrid.Rows.Add(New Object() {3, "Item C", "C1", "C2"})
            bsData.DataSource = dtGrid
        End Sub
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            MockedData1()
            Dim dtGrid = CType(bsData.DataSource, DataTable)
            For Each item In NoShowColumns
                If dtGrid.Columns.Contains(item) Then
                    dtGrid.Columns(item).ColumnMapping = MappingType.Hidden
                End If
            Next
            DataGridView1.DataSource = Nothing
            DataGridView1.DataSource = bsData
        End Sub
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            MockedData2()
            Dim dtGrid = CType(bsData.DataSource, DataTable)
            For Each item In NoShowColumns
                If dtGrid.Columns.Contains(item) Then
                    dtGrid.Columns(item).ColumnMapping = MappingType.Hidden
                End If
            Next
            DataGridView1.DataSource = Nothing
            DataGridView1.DataSource = bsData
        End Sub
    End Class


    KSG

    • Marked as answer by Mike Dos Zhang Wednesday, March 7, 2012 11:25 AM
    Thursday, March 1, 2012 11:19 AM
  • Never done it, but I imagin Amit's solution is the most straightforward.  First assign the data source and allow the DGV to auto-generate the columns.  Then hide the columns based on whether you are in case A or case B.

    You should also know that the DGV, in lieu of a better source (meaning the ITypedList interface), it resorts to listing the properties of the object by querying the first object in the data source of a collection of property descriptors, and I bet any default implementation of ITypedList.GetItemProperties() does this too by default.  This means that you can implement ICustomTypeDescriptor in your classes (if you are binding to a collection of classes) to control at runtime which property descriptors are made visible to the DGV.  Hell, maybe it is as simple as setting the BrowsableAttribute attribute!  Try it out if you fancy it.  May work as easily.


    Jose R. MCP

    • Marked as answer by Mike Dos Zhang Wednesday, March 7, 2012 11:25 AM
    Thursday, March 1, 2012 1:44 PM

All replies

  • You have two options:  Let the DGV auto-generate columns (I think it is the default behavior), or create the columns manually yourself.  I'd go with #1 unless the default behavior is not good enough for you for whatever reason.  This behavior is controlled by the property called AutoGenerateColumns.

    Jose R. MCP

    • Marked as answer by Mike Dos Zhang Wednesday, March 7, 2012 11:25 AM
    Wednesday, February 29, 2012 5:46 PM
  • What is the difference in no of columns for option A & B? If you have few columns, you can set the visible property of column as and when required. And instead of adding column at run time, can't you just bind with datasource?

    Amit Govil | Email

    "Weeks of coding can save you hours of planning"

    • Marked as answer by Mike Dos Zhang Wednesday, March 7, 2012 11:25 AM
    Wednesday, February 29, 2012 5:52 PM
  • If your DataSource for both options is a DataTable meaning the BindingSource.DataSource = SomeDataTable then you can set column mappings of the columns not to display in the DataGridView once the DataTable has been populated. So set columns that you do not want to show as Hidden.

    MSDN Reference


    KSG

    • Marked as answer by Mike Dos Zhang Wednesday, March 7, 2012 11:25 AM
    Wednesday, February 29, 2012 11:00 PM
  • The columns are auto-generated. There are 2-4 columns I want to hide depending on the table binded to.

    How do I specify what columns to hide when the column name is only generated at runtime?

    Thursday, March 1, 2012 10:39 AM
  • The columns are auto-generated. There are 2-4 columns I want to hide depending on the table binded to.

    How do I specify what columns to hide when the column name is only generated at runtime?

    You have an array perhaps that has column names not to display no matter what or if the logic is dependent on other things you might have a multi-dimensional array etc. The example below shows two hard coded DataTables used as the data source for a BindingSource which in turn becomes the data source of a DataGridView. After the DataTable is populated and used as the source as mentioned we cycle thru an array of column names, if found hide the column. Hope is clear and assist you with making a decision.

    Public Class frmSelectiveColDemo
        ''' <summary>
        ''' Columns not to display
        ''' </summary>
        ''' <remarks></remarks>
        Private NoShowColumns As String() = {"Process", "Column1"}
        WithEvents bsData As New BindingSource
        Private Sub MockedData1()
            Dim dtGrid As New DataTable()
            dtGrid.Columns.AddRange(New DataColumn() _
                { _
                    New DataColumn("Process", GetType(System.Boolean)), _
                    New DataColumn("Identifier", GetType(System.Int32)), _
                    New DataColumn("Column1", GetType(System.String)), _
                    New DataColumn("Part", GetType(System.String)) _
                } _
            )
            dtGrid.Rows.Add(New Object() {False, 1, "A1", "Item A"})
            dtGrid.Rows.Add(New Object() {False, 2, "B1", "Item B"})
            dtGrid.Rows.Add(New Object() {False, 3, "C1", "Item C"})
            bsData.DataSource = dtGrid
        End Sub
        Private Sub MockedData2()
            Dim dtGrid As New DataTable()
            dtGrid.Columns.AddRange(New DataColumn() _
                { _
                    New DataColumn("Identifier", GetType(System.Int32)), _
                    New DataColumn("Column1", GetType(System.String)), _
                    New DataColumn("Column2", GetType(System.String)), _
                    New DataColumn("Item", GetType(System.String)) _
                } _
            )
            dtGrid.Rows.Add(New Object() {1, "Item A", "A1", "A2"})
            dtGrid.Rows.Add(New Object() {2, "Item B", "B1", "B2"})
            dtGrid.Rows.Add(New Object() {3, "Item C", "C1", "C2"})
            bsData.DataSource = dtGrid
        End Sub
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            MockedData1()
            Dim dtGrid = CType(bsData.DataSource, DataTable)
            For Each item In NoShowColumns
                If dtGrid.Columns.Contains(item) Then
                    dtGrid.Columns(item).ColumnMapping = MappingType.Hidden
                End If
            Next
            DataGridView1.DataSource = Nothing
            DataGridView1.DataSource = bsData
        End Sub
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            MockedData2()
            Dim dtGrid = CType(bsData.DataSource, DataTable)
            For Each item In NoShowColumns
                If dtGrid.Columns.Contains(item) Then
                    dtGrid.Columns(item).ColumnMapping = MappingType.Hidden
                End If
            Next
            DataGridView1.DataSource = Nothing
            DataGridView1.DataSource = bsData
        End Sub
    End Class


    KSG

    • Marked as answer by Mike Dos Zhang Wednesday, March 7, 2012 11:25 AM
    Thursday, March 1, 2012 11:19 AM
  • The default column names would be same as you have in your datatable or in the bindingsource(basically it would be the column name that you have in your  table in database). check code below to hide column.

    DataGridView1.Columns["ColumnName"].Visible=False;


    Amit Govil | Email

    "Weeks of coding can save you hours of planning"


    Thursday, March 1, 2012 12:14 PM
  • Never done it, but I imagin Amit's solution is the most straightforward.  First assign the data source and allow the DGV to auto-generate the columns.  Then hide the columns based on whether you are in case A or case B.

    You should also know that the DGV, in lieu of a better source (meaning the ITypedList interface), it resorts to listing the properties of the object by querying the first object in the data source of a collection of property descriptors, and I bet any default implementation of ITypedList.GetItemProperties() does this too by default.  This means that you can implement ICustomTypeDescriptor in your classes (if you are binding to a collection of classes) to control at runtime which property descriptors are made visible to the DGV.  Hell, maybe it is as simple as setting the BrowsableAttribute attribute!  Try it out if you fancy it.  May work as easily.


    Jose R. MCP

    • Marked as answer by Mike Dos Zhang Wednesday, March 7, 2012 11:25 AM
    Thursday, March 1, 2012 1:44 PM
  • Thanks!

    In this situation, am I better off to create views and in each view specify the columns required?

    Thanks again

    Thursday, March 1, 2012 4:34 PM
  • What the "view" do you mean?

    I think setting the Visible property way will be easier to use than the way webJose told you for you.


    Mike Zhang[MSFT]
    MSDN Community Support | Feedback to us

    Wednesday, March 7, 2012 11:27 AM