Mike Cole
Mike Cole

Reputation: 14753

Changing GridView column properties from code-behind

I am creating a GridView in a method like so:

GridView gridView = new GridView();
gridView.DataSource = reportData.Tables[0];
gridView.DataBind();

I am later exporting it to Excel and it works great. The columns are being auto-generated from my source data. I would like to change the DataFormatString property of some of the columns however after I databind and before I export to Excel. I can't seem to find the correct property to change. Can anybody point me in the right direction?

Upvotes: 5

Views: 17609

Answers (4)

Kobi
Kobi

Reputation: 138147

According to AutoGenerateColumns documentation:

This option provides a convenient way to display every field in the data source; however, you have limited control of how an automatically generated column field is displayed or behaves.

Note: Automatically generated bound column fields are not added to the Columns collection.

I tired looking for these AutoGeneratedFields with no luck.
I can think of several options to achieve that (from worst to best):

  1. Add an event to the grid (like RowDataBound), this will give you access to the rows' cells, but isn't too convenient.
  2. Don't use AutoGeneratedField Create these columns manually, as in:

    BoundField dateField = new BoundField();
    dateField.HeaderText = "Date";
    dateField.DataField = "date";
    dateField.DataFormatString = "{0:MMMM, yyyy}";
    gridView.Columns.Add(dateField); 
    

    This options gives you bes control over titles.

  3. Add another layer for data formatting and presentation. This is probably the best option. Also, that way you don't have to use DataTables, a GridView can by bound to any collection of objects with public properties (eg, to a List<Employee)), and AutoGeneratedField turns them into columns.
    I think this is the best option. Suppose you could access the auto columns, what then? You'd have to search for a column based on its name or index, which seems very messy, and increases coupling.

And, as a last note, you should think about creating Excel files by using the API. It's not as easy, but HTML XLS files are less compatible with Excel 2007 - it displays a warning message that the format of the file is incompatible with the extension, and worse, the file brakes if it is opened and saves (can be Save As though), making your files less user-friendly.

Upvotes: 7

Dan Diplo
Dan Diplo

Reputation: 25359

Here's an extract from a GridView exporter I wrote that converts controls in a GridView into literals that are re-formated. It might be of some help:

        /// <summary>
    /// Parses and cleans up data from the GridView controls collection
    /// to make the data more suitable for Exported
    /// </summary>
    /// <param name="gv">The GridView to parse</param>
    private void CleanUpControls(Control gv)
    {
        Literal l = new Literal();

        for (int i = 0; i < gv.Controls.Count; i++)
        {

            if (gv.Controls[i].GetType() == typeof (LinkButton))
            {
                l.Text = (gv.Controls[i] as LinkButton).Text;
                ReplaceWithLiteral(gv, l, i);
            }
            else if (gv.Controls[i].GetType() == typeof (ListControl))
            {
                l.Text = (gv.Controls[i] as ListControl).SelectedItem.Text;
                ReplaceWithLiteral(gv, l, i);
            }
            else if (gv.Controls[i].GetType() == typeof (CheckBox))
            {
                l.Text = (gv.Controls[i] as CheckBox).Checked ? "True" : "False";
                ReplaceWithLiteral(gv, l, i);
            }
            else if (gv.Controls[i].GetType() == typeof (BooleanImage))
            {
                l.Text = (gv.Controls[i] as BooleanImage).Value ? "True" : "False";
                ReplaceWithLiteral(gv, l, i);
            }
            else if (gv.Controls[i].GetType().ToString() == "System.Web.UI.WebControls.PagerTable")
                ReplaceWithLiteral(gv, l, i);

            else if (gv.Controls[i].GetType() == typeof (HyperLink))
            {
                HyperLink hl = gv.Controls[i] as HyperLink;
                if (MakeHyperLinksAbsolute)
                {
                    if (hl != null)
                        hl.NavigateUrl = UrlHelper.MakeAbsoluteUrl(hl.NavigateUrl);
                }

                switch (TreatHyperLinksAs)
                {
                    case HyperLinkMode.Text:
                        l.Text = hl.Text;
                        ReplaceWithLiteral(gv, l, i);
                        break;

                    case HyperLinkMode.NavigateUrl:
                        if (hl != null) l.Text = hl.NavigateUrl;
                        ReplaceWithLiteral(gv, l, i);
                        break;

                    case HyperLinkMode.ToolTip:
                        l.Text = hl.ToolTip;
                        ReplaceWithLiteral(gv, l, i);
                        break;

                    case HyperLinkMode.TextAndLink:
                        l.Text = String.Format("{0} ({1})", hl.Text, hl.NavigateUrl);
                        ReplaceWithLiteral(gv, l, i);
                        break;

                    case HyperLinkMode.HyperLink:
                        break;
                }
            }

            if (gv.Controls[i].HasControls())
                CleanUpControls(gv.Controls[i]);
        }
    }

Upvotes: -1

Jo&#227;o Silva
Jo&#227;o Silva

Reputation: 91359

For example:

String newDataFormatString = "{0:d}";
BoundField bf = gridView.Columns[Index] as BoundField;
if (bf != null) {
    bf.DataFormatString = "{0}"; // workaround to sync with ViewState (it's documented)
    bf.DataFormatString = newDataFormatString;
}

Upvotes: 0

smok1
smok1

Reputation: 2950

This is the issue of how asp.net works. When you create some controls (columns) in a method and set this controls set to user, the next time user post backs data to you, you do not have access to those columns since they … do not exists. Every time you display your site, a brand new object (instance) is created.
The only way to be able to get data in post back from previously created controls is to create controls in Page_Init method…

Upvotes: -1

Related Questions