Keep it MVC. Use templated controls without injecting Eval() in your aspx.

I am quite stubborn in keeping .aspx clean, try to keep only asp and html tag in it.

Until recently I need to use ListView and bind my data to it, almost 90% of the example available are using <%# Eval(“[PropertyName]”) %>.

But I really don’t want to stuff my .aspx with these things, I don’t know if they are VBScript or ASP code, anyway, I want to do that in C# code.

I image that is possible to customize my binding just like I did in Java. After searching and reading articles for a few hours, I finally got it.

I want to share my experience here hoping to save someone a few hours. I will try to give sample code download if I can.

First step, drag a ListView control to your page. There are three things a ListView must have.

1.You must have a <LayoutTemplate> in your ListView.

2.You must have a <PlaceHolder> in your <LayoutTemplate>.

3.Set ItemPlaceholderId to your PlaceHolder Id.

I am using table to display my data. You will result in something that looks like this:

<asp:ListView ID="ltv_users" runat="server" ItemPlaceholderID="plh_userItems"
        onitemcommand="ltv_users_ItemCommand"
        ondatabinding="ltv_users_DataBinding" onitemdeleting="ltv_users_ItemDeleting">
        <LayoutTemplate>
            <table class="ListViewTableStyle" border="1">
                <thead class="ListViewHeaderStyle">
                    <tr>
                        <td>
                        </td>
                        <td>
                            Column Header 1
                        </td>
                        <td>
                            Column Header 2
                        </td>
                    </tr>
                </thead>
                <tbody>
                    <asp:PlaceHolder ID="plh_userItems" runat="server"></asp:PlaceHolder>
                </tbody>
            </table>
        </LayoutTemplate>
    </asp:ListView>

Second Step is to define your own customize Template to do data binding. Create a class which implement ITemplate interface under System.Web.UI namespace. People usually pass an enumerator to the constructor to indicate what type of template to create. The result looks like this.

public class UserTemplate : ITemplate
    {
        protected ListViewTemplateType m_templateType;
        public UserTemplate(ListViewTemplateType type)
        {
            m_templateType = type;
        }
    }

ListViewTemplateType is just an enumerator one to one maps to template available inside ListView tag. Then we implement two methods, InstantiateIn(Control container) which response for creating html tags and data binding method. Here is an example for generating different tags for different template.

public void InstantiateIn(Control container)
        {
            //for itemtemplate and alternativeitemtemplate
            LinkButton l_btnDetail = new LinkButton() { Text = m_DetailBtnText, ID = "btnDetail", CommandName = "Detail", CssClass = "ListViewButton" };
            LinkButton l_btnRole = new LinkButton() { Text = m_RoleBtnText, ID = "btnRole", CommandName = "Role", CssClass = "ListViewButton" };
            LinkButton l_btnDelete = new LinkButton() { Text = m_DeleteBtnText, ID = "btnDelete", CommandName = "Delete", CssClass = "ListViewButton" };
            Label l_lblAccount = new Label() { ID = "lblAccount" };
            Label l_lblUserName = new Label() { ID = "lblUserName" };
            switch (m_templateType)
            {
                //ListViewItemType.
                case ListViewTemplateType.ItemTemplate:
                    container.Controls.Add(new LiteralControl("<tr class=\"ListViewItemStyle\"><td>"));
                    container.Controls.Add(l_btnDetail);
                    container.Controls.Add(l_btnRole);
                    container.Controls.Add(l_btnDelete);
                    container.Controls.Add(new LiteralControl("</td><td>"));
                    container.Controls.Add(l_lblAccount);
                    container.Controls.Add(new LiteralControl("</td><td>"));
                    container.Controls.Add(l_lblUserName);
                    container.Controls.Add(new LiteralControl("</td></tr>"));
                    container.DataBinding += new EventHandler(ItemTemplate_DataBinding);
                    break;
                case ListViewTemplateType.AlternatingItemTemplate:
                    container.Controls.Add(new LiteralControl("<tr class=\"ListViewAlternativeItemStyle\"><td>"));
                    container.Controls.Add(l_btnDetail);
                    container.Controls.Add(l_btnRole);
                    container.Controls.Add(l_btnDelete);
                    container.Controls.Add(new LiteralControl("</td><td>"));
                    container.Controls.Add(l_lblAccount);
                    container.Controls.Add(new LiteralControl("</td><td>"));
                    container.Controls.Add(l_lblUserName);
                    container.Controls.Add(new LiteralControl("</td></tr>"));
                    container.DataBinding += new EventHandler(ItemTemplate_DataBinding);
                    break;
            }
        }

We need to define controls id so that we can later bind data to them by their id in ItemTemplate_DataBinding().

public void ItemTemplate_DataBinding(object sender, EventArgs e)
        {
            ListViewDataItem listViewDataItem = (ListViewDataItem)sender;
            string l_account = (string)DataBinder.Eval(listViewDataItem.DataItem, "Account");
            string l_userName = (string)DataBinder.Eval(listViewDataItem.DataItem, "FirstName") + (string)DataBinder.Eval(listViewDataItem.DataItem, "LastName");
            Guid l_userId = (Guid)DataBinder.Eval(listViewDataItem.DataItem, "Id");
            switch (m_templateType)
            {
                case ListViewTemplateType.ItemTemplate:
                case ListViewTemplateType.AlternatingItemTemplate:
                    ((LinkButton)listViewDataItem.FindControl("btnDetail")).CommandArgument = l_userId.ToString();
                    ((LinkButton)listViewDataItem.FindControl("btnRole")).CommandArgument = l_userId.ToString();
                    //((LinkButton)listViewDataItem.FindControl("btnDelete")).CommandArgument = l_userId.ToString();
                    LinkButton btnDelete = (LinkButton)listViewDataItem.FindControl("btnDelete");
                    btnDelete.CommandArgument = l_userId.ToString();
                    btnDelete.OnClientClick = m_ConfirmScript;
                    ((Label)listViewDataItem.FindControl("lblAccount")).Text = l_account;
                    ((Label)listViewDataItem.FindControl("lblUserName")).Text = l_userName;
                    break;
            }
        }

I am using a fall through here because ItemTemplate and AlternatingItemTemplate are binding data in the same way. You can bind textbox for ItemEditTemplate. I am going to show how to use this template class we make just now. How to work under asp page life cycle and use your own data source, and something about default ListView event handling. Read It Now!

Advertisements

Modify Web.Config Programmatically

The gives me a headache for couple of days, and I finally solve this puzzle which everyone else gets no trouble in doing it.

First of all, let me explain some background knowledge on web.config which is the reason why I got into trouble with.

There is a hierarchy on configuration, machine.config->web.config(root)->web.config(app)->web.config(sub)

the latter ones override the previous ones.

machine.config and web.config(root) can be found at

%WINDIR%\Microsoft.NET\Framework\[version]\CONFIG\

[version] is your .NET framework version.

Now, let’s start to dicuss how to modify web.config(app).

System.Configuration.Configuration l_webConfig = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(m_webConfig, m_website, null, Server.MachineName, l_iisUserName, l_iisPassword);
AppSettingsSection l_appSetting = l_webConfig.AppSettings;
ConnectionStringsSection l_connSetting = l_webConfig.ConnectionStrings;+
//Get a setting from appSettings section
string l_appValue = l_appSetting.Settings["key"].value
//Get a connection string from connectionStringsSection
string l_connValue = l_connSetting.ConnectionStrings["ConnectionString"].ConnectionString
//Add a new appSetting
l_appSetting.Settings.Add("key","value")
//Add a new connection string
l_connSetting.ConnectionStrings.Add(new ConnectionStringSettings("name","value"))
//save it
l_webConfig.save(ConfigurationSaveMode.Minimal);

The first line open up a web.config, I am using one of its overload only.

The first parameter is the path where your application web.config locate, usually is “~”.

The second parameter is your website name, default value is “Default Web site”.

The third one is subLocationPath, I am not sure what this is. this might be for web.config(sub).

The fourth one is host name. 5th and 6th parameters is the server administrator account/password.

After modifying your configuration, save it back to the database.

There are three save mode which is self-explanatory.

 

I get two problems when trying to modify web.config.

The first one is, it will tells you that AllowLocation=false, can not modify web.config.

When this happens, set it to true in your machine.config.

Another one is, when you are not using account/password to open web.config.

If you are running in Visual Studio, it will use ASP.NET account to open it.

If you are running in IIS, it will use IIS account or NETWORK SERVICES account.

Make sure the account that your are using has the permission to modify web.config file.